在本文中,我們將學習如何爲您的Kubernetes環境(簡稱k8s)設置監視堆棧。 這種解決方案使您的團隊可以在幾乎不影響現有資源的情況下獲得對基礎架構和每個應用程序的可見性。
可觀測性的目的是向負責生產的操作員提供工具,以檢測不良行爲(服務停機,錯誤,響應速度慢),並提供可操作的信息以查找問題的根本原因。 它通常分爲三個支柱:
- 指標:提供有關係統每個組件的時間序列信息,例如CPU,內存,磁盤和網絡消耗,並且通常顯示整體前景以及在特定時間檢測異常行爲的第一步。
- 日誌:爲操作員提供了一種工具,可以將機器,服務和應用程序日誌集中在同一可搜索數據庫中,以分析和了解系統上的意外行爲。
- 跟蹤或APM(應用程序監視性能):提供了對應用程序的更深入的瞭解,其中記錄了服務執行中的每個請求和步驟(http調用,數據庫查詢等)。 使用跟蹤,我們可以檢測到性能低下或調試低級別的特定用戶,並相應地改進或修復我們的系統。
360可觀察性的概念與devop和敏捷原則完全一致,可以隨着時間的推移不斷觀察,檢測和改進系統。
在本文中,我們將在Kubernetes環境中使用由Elasticsearch,Kibana,Filebeat,Metricbeat和APM-Server組成的Elastic堆棧(版本7.6.2)監視和記錄生產環境。 本系列文章將逐步介紹標準的Kubernetes部署,在我看來,它可以更好地全面瞭解安裝和配置的每個步驟。 當然,還存在其他方法來在Kubernetes上使用Helm或Elastic Cloud之類的工具來安裝和配置某些服務,但是本文的目的是使讀者充分了解這種``相當''複雜的體系結構中的每個組件,以幫助他們進行調整 適用於自己的系統,有時會受到自動安裝程序的限制。
前提條件
本教程使用minikube創建本地k8s環境,並部署一個簡單的應用程序,該應用程序由Spring-Boot服務和MongoDB數據庫組成,將用作示例來監視和跟蹤系統及應用程序的行爲。
因此,爲了開始使用,需要以下工具:
- Docker:容器引擎
- minikube:用於開發和測試的本地kubernetes
- kubectl:Kubernetes命令行工具
- Elasticsearch要求增加主機上的nmapfs(虛擬內存)(請參閱詳細信息)針對Linux系統我們需要運行如下的命令:
$ sudo sysctl -w vm.max_map_count=262144
如果你還沒沒有安裝好自己的Minikube的話,那麼請參照我之前的文章“Elastic Cloud Kubernetes (ECK) 部署”。
配置minikube 內存大小
首先,我們將分配給minikube主機的默認內存大小(2GB)增加到8GB。 在終端中運行以下命令:
minikube config set memory 8192
$ minikube config set memory 8192
❗ These changes will take effect upon a minikube delete and then a minikube start
啓動minikube
現在,使用以下命令啓動minikube。 可能要花幾分鐘...。針對中國的情況,我們使用如下命令來啓動minikube:
minikube start --driver=virtualbox --cpus 3 --memory 8196 --image-repository='registry.cn-hangzhou.aliyuncs.com/google_containers'
$ minikube start --driver=virtualbox --cpus 3 --memory 8196 --image-repository='registry.cn-hangzhou.aliyuncs.com/google_containers'
😄 minikube v1.9.2 on Darwin 10.15.4
✨ Using the virtualbox driver based on existing profile
✅ Using image repository registry.cn-hangzhou.aliyuncs.com/google_containers
👍 Starting control plane node m01 in cluster minikube
🏃 Updating the running virtualbox "minikube" VM ...
🐳 Preparing Kubernetes v1.18.0 on Docker 19.03.8 ...
🌟 Enabling addons: default-storageclass, storage-provisioner
🏄 Done! kubectl is now configured to use "minikube"
❗ /usr/local/bin/kubectl is v1.15.5, which may be incompatible with Kubernetes v1.18.0.
💡 You can also use 'minikube kubectl -- get pods' to invoke a matching versio
檢查Minikube的狀態
我們可以檢查minikube的狀態:
minikube status
$ minikube status
m01
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
kubectl get nodes
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready master 23m v1.18.0
我們可以看到我們有一個master,並且Kubernetes的版本是1.18。
部署樣本應用程序
現在,我們將部署一個簡單的應用程序(Spring-Boot)及其數據庫(MongoDB)。
MongoDB
我們首先在k8s環境中部署MongoDB,並公開端口27017。
mongo.yml
---
apiVersion: v1
kind: Service
metadata:
namespace: default
name: mongo
labels:
app: mongo
spec:
ports:
- port: 27017
protocol: TCP
selector:
app: mongo
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
namespace: default
name: mongo
labels:
app: mongo
spec:
serviceName: "mongo"
replicas: 1
selector:
matchLabels:
app: mongo
template:
metadata:
labels:
app: mongo
spec:
containers:
- name: mongo
image: mongo
ports:
- containerPort: 27017
volumeMounts:
- name: mongo-persistent-storage
mountPath: /data/db
volumeClaimTemplates:
- metadata:
name: mongo-persistent-storage
annotations:
volume.beta.kubernetes.io/storage-class: "standard"
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: standard
resources:
requests:
storage: 1Gi
使用以下命令部署MongoDB:
kubectl apply -f mongo.yml
我們等一下直到它運行起來:
kubectl get pods
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
mongo-0 1/1 Running 0 114s
kubectl get all -l app=mongo
$ kubectl get all -l app=mongo
NAME READY STATUS RESTARTS AGE
pod/mongo-0 1/1 Running 0 2m31s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/mongo ClusterIP 10.104.205.22 <none> 27017/TCP 14m
NAME READY AGE
statefulset.apps/mongo 1/1 2m31s
spring-boot-simple
現在讓我們部署我們的Spring-Boot API。 它將API內部部署在端口8080上,但是type = NodePort也可以從節點靜態IP在另一個端口上進行訪問。
spring-boot-simple.yml
# spring-boot-simple.yml
---
apiVersion: v1
kind: Service
metadata:
namespace: default
name: spring-boot-simple
labels:
app: spring-boot-simple
spec:
type: NodePort
ports:
- port: 8080
protocol: TCP
selector:
app: spring-boot-simple
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: spring-boot-simple
labels:
app: spring-boot-simple
spec:
replicas: 1
selector:
matchLabels:
app: spring-boot-simple
template:
metadata:
labels:
app: spring-boot-simple
spec:
containers:
- image: gjeanmart/spring-boot-simple:0.0.1-SNAPSHOT
imagePullPolicy: Always
name: spring-boot-simple
env:
- name: SPRING_DATA_MONGODB_HOST
value: mongo
ports:
- containerPort: 8080
運行命令以部署spring-boot-simple:
kubectl apply -f spring-boot-simple.yml
然後等它部署好:
kubectl get all -l app=spring-boot-simple
$ kubectl get all -l app=spring-boot-simple
NAME READY STATUS RESTARTS AGE
pod/spring-boot-simple-84c965c78c-xknw9 1/1 Running 0 5m31s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/spring-boot-simple NodePort 10.110.22.185 <none> 8080:30894/TCP 5m31s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/spring-boot-simple 1/1 1 1 5m31s
NAME DESIRED CURRENT READY AGE
replicaset.apps/spring-boot-simple-84c965c78c 1 1 1 5m31s
注意節點上API的外部端口:30049,並使用$ minikube ip獲得節點靜態IP。
$ minikube ip
192.168.99.118
我們也可以通過如下的方法來找到service的port號:
export NODE_PORT=$(kubectl get service/spring-boot-simple -o go-template='{{(index .spec.ports 0).nodePort}}')
echo $NODE_PORT
$ echo $NODE_PORT
30894
獲得所需的所有信息後,只需運行以下命令以測試我們的示例API(將<IP>:<PORT>替換爲您的值)。
Greetings
curl $(minikube ip):30894
$ curl $(minikube ip):30894
Greetings from Spring Boot!liuxg:minikube
Post 一個信息
curl -X POST $(minikube ip):30894/message -d 'hello world'
$ curl -X POST $(minikube ip):30894/message -d 'hello world'
{"id":"5eac196bcff47e0001297d16","message":"hello+world=","postedAt":"2020-05-01T12:43:23.944+0000"}
Get 所有信息
curl -X GET $(minikube ip):30894/message
$ curl -X GET $(minikube ip):30894/message
[{"id":"5eac196bcff47e0001297d16","message":"hello+world=","postedAt":"2020-05-01T12:43:23.944+0000"}]
創建 monitoring 的命名空間
最後,爲了在邏輯上將監視堆棧與應用程序分開(namespace default),我們將所有內容部署在稱爲monitoring的命名空間下。
要創建namespace,只需運行以下命令:
kubectl create namespace monitoring
你也可以通過如下的方式來創建。先創建一個yaml文件。
monitoring.namespace.yml
# monitoring.namespace.yml
---
apiVersion: v1
kind: Namespace
metadata:
name: monitoring
---
讓後,使用如下的命令來創建:
kubectl apply -f monitoring.namespace.yml
在下一步,我們將安裝Elasticsearch及Kibana。請閱讀我的另外一篇文章。