Elastic:运用 Elastic Stack 对 Kubernetes 进行监控 (一)

在本文中,我们将学习如何为您的 Kubernetes 环境(简称 k8s)设置监视堆栈。 这种解决方案使您的团队可以在几乎不影响现有资源的情况下获得对基础架构和每个应用程序的可见性。

可观测性的目的是向负责生产的操作员提供工具,以检测不良行为(服务停机,错误,响应速度慢),并提供可操作的信息以查找问题的根本原因。 它通常分为三个支柱:

  • 指标:提供有关系统每个组件的时间序列信息,例如 CPU,内存,磁盘和网络消耗,并且通常显示整体前景以及在特定时间检测异常行为的第一步。
  • 日志:为操作员提供了一种工具,可以将机器,服务和应用程序日志集中在同一可搜索数据库中,以分析和了解系统上的意外行为。
  • 跟踪或 APM(应用程序监视性能):提供了对应用程序的更深入的了解,其中记录了服务执行中的每个请求和步骤(http 调用,数据库查询等)。 使用跟踪,我们可以检测到性能低下或调试低级别的特定用户,并相应地改进或修复我们的系统。

出处:Peter Bourgon

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

关于如何在不同的操作系统上设置这个,请参阅链接 Using docker images in production

如果你还没没有安装好自己的 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=docker --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-xmkcq   1/1     Running   0          14m


NAME                         TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/spring-boot-simple   NodePort   10.101.241.38   <none>        8080:30202/TCP   14m


NAME                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/spring-boot-simple   1/1     1            1           14m

NAME                                            DESIRED   CURRENT   READY   AGE
replicaset.apps/spring-boot-simple-84c965c78c   1         1         1       14m

注意节点上 API 的外部端口:30202,并使用 $ minikube ip 获得节点静态 IP。

$ minikube ip
127.0.0.1

我们也可以通过如下的方法来找到 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>替换为您的值)。

对于使用 Docker 来说,在实际的操作中我发现这个端口号并不是直接可以在 host 中之间使用的。我们可以通过如下的方法来找到在 host 中可以使用的端口号:

minikube service spring-boot-simple --url
$ minikube service spring-boot-simple --url
🏃  Starting tunnel for service spring-boot-simple.
|-----------|--------------------|-------------|------------------------|
| NAMESPACE |        NAME        | TARGET PORT |          URL           |
|-----------|--------------------|-------------|------------------------|
| default   | spring-boot-simple |             | http://127.0.0.1:56611 |
|-----------|--------------------|-------------|------------------------|
http://127.0.0.1:56611
❗  Because you are using docker driver on Mac, the terminal needs to be open to run it.

请注意上面显示的端口号56611。这个端口号将在如下的 API 中进行使用。请使用这个值替换如下的端口号。

Greetings

curl $(minikube ip):port
$ curl $(minikube ip):56611
Greetings from Spring Boot!liuxg:minikube

Post 一个信息

curl -X POST $(minikube ip):56611/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):56611/message
$ curl -X GET $(minikube ip):56611/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。请阅读我的另外一篇文章 “运用 Elastic Stack 对 Kubernetes 进行监控 (二)”。在那篇文章中,我们将详细介绍如何安装 Elasticsearch Stack。

参考:

【1】https://github.com/kubernetes/kubernetes/issues/39823

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值