在本文中,我们将学习如何为您的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。请阅读我的另外一篇文章。