01 引言
本文是一篇阅读笔记,参考原文地址:https://yunlzheng.gitbook.io/prometheus-book/part-iii-prometheus-shi-zhan/readmd/kubernetes-with-minikube
02 初识Kubernetes
Kubenetes(又名k8s
)源码地址:https://github.com/kubernetes/kubernetes
Kubenetes
是一款由Google
开发的开源的容器编排工具
Kubernetes
将一系列的主机看做是一个受管理的海量资源,这些海量资源组成了一个能够方便进行扩展的操作系统;Kubernetes
中运行着的容器则可以视为是这个操作系统中运行的“进程”,通过Kubernetes
这一中央协调器,解决了基于容器应用程序的调度、伸缩、访问负载均衡以及整个系统的管理和监控的问题。
2.1 Kubernetes应用管理模型
2.1.1 Pod和Controller
什么是Pod?
Pod
是Kubernetes
中的最小调度资源;Pod
中会包含一组容器,它们一起工作,并且对外提供一个(或者一组)功能,对于这组容器而言它们共享相同的网络和存储资源,因此它们之间可以直接通过本地网络(127.0.0.1)进行访问;- 当
Pod
被创建时,调度器(kube-schedule
)会从集群中找到满足条件的节点运行它。
什么是Controller?
- 如果部署应用程序时,需要启动多个实例(副本),则需要使用到控制器(
Controller
); - 用户可以在
Controller
定义Pod
的调度规则、运行的副本数量以及升级策略等等信息,当某些Pod
发生故障之后,Controller
会尝试自动修复,直到Pod
的运行状态满足Controller
中定义的预期状态为止; Kubernetes
中提供了多种Controller
的实现,包括:Deployment
(无状态应用)、StatefulSet
(有状态应用)、Daemonset
(守护模式)等,以支持不同类型应用的部署和调度模式。
可以知道,通过Controller和Pod我们定义了应用程序是如何运行的?
2.1.1 Kubernetes通信
Kubernetes
的应用管理模型如下:
2.1.1.1 Kubernetes集群内的应用如何通信?
解决方式:如上图,在Kubernetes中通过定义Service(服务)来解决。
步骤如下:
Service
在Kubernetes
集群内扮演了服务发现和负载均衡的作用;- 在
Kubernetes
下部署的Pod
实例都会包含一组描述自身信息的Lable
,而创建Service
,可以声明一个Selector
(标签选择器); Service
通过Selector
,找到匹配标签规则的Pod
实例,并将对Service
的请求转发到代理的Pod
中;Service
创建完成后,集群内的应用就可以通过使用Service
的名称作为DNS
域名进行相互访问。
2.1.1.2 外部的用户如何访问集群内的应用?
解决方式:如上图,Kubernetes中定义了单独的资源Ingress(入口)。
Ingress
是一个工作在7层的负载均衡器,其负责代理外部进入集群内的请求,并将流量转发到对应的服务中。
最后,对于同一个Kubernetes
集群其可能被多个组织使用,为了隔离这些不同组织创建的应用程序,Kubernetes
定义了Namespace
(命名空间)对资源进行隔离。
2.2 Kubernetes架构模型
Kubernetes
架构模型图如下:
Kubernetes
的核心组件主要由两部分组成,Master
组件和Node
组件,其中:
Matser
组件提供了集群层面的管理功能,它们负责响应用户请求并且对集群资源进行统一的调度和管理;Node
组件会运行在集群的所有节点上,它们负责管理和维护节点中运行的Pod
,为Kubernetes
集群提供运行时环境。
2.2.1 Master组件
Master组件主要包括:
kube-apiserver
:负责对外暴露Kubernetes API;etcd
:用于存储Kubernetes集群的所有数据;kube-scheduler
: 负责为新创建的Pod选择可供其运行的节点;kube-controller-manager
: 包含Node Controller,Deployment Controller,Endpoint Controller等等,通过与apiserver交互使相应的资源达到预期状态。
2.2.2 Node组件
Node组件主要包括:
kubelet
:负责维护和管理节点上Pod的运行状态;kube-proxy
:负责维护主机上的网络规则以及转发。Container Runtime
:如Docker、rkt、runc等提供容器运行时环境。
2.3 Kubernetes监控策略
2.3.1 从两个层面理解Kubernetes指标
物理结构上讲:Kubernetes
主要用于整合和管理底层的基础设施资源,对外提供应用容器的自动化部署和管理能力,这些基础设施可能是物理机、虚拟机、云主机等等。因此,基础资源的使用直接影响当前集群的容量和应用的状态。在这部分,我们需要关注集群中各个节点的主机负载,CPU
使用率、内存使用率、存储空间以及网络吞吐等监控指标。
自身架构上讲:kube-apiserver
是Kubernetes
提供所有服务的入口。无论是外部的客户端还是集群内部的组件都直接与kube-apiserver
进行通讯。因此,kube-apiserver
的并发和吞吐量直接决定了集群性能的好坏,我们需要评价其自身的服务质量,主要关注在Kubernetes
的API
响应时间,以及Pod
的启动时间等指标上。
2.3.2 监控Kubernetes关键点
Kubernetes
的最终目标还是需要为业务服务,因此我们还需要能够监控应用容器的资源使用情况。对于内置了对Prometheus
支持的应用程序,也要支持从这些应用程序中采集内部的监控指标。
综上所述,我们需要综合使用白盒监控和黑盒监控模式,建立从基础设施,Kubernetes
核心组件,应用容器等全面的监控体系。
2.3.2.1 白盒层控制面
在白盒监控层面我们需要关注:
- 基础设施层(Node):为整个集群和应用提供运行时资源,需要通过各节点的
kubelet
获取节点的基本状态,同时通过在节点上部署Node Exporter
获取节点的资源使用情况; - 容器基础设施(Container):为应用提供运行时环境,
Kubelet
内置了对cAdvisor
的支持,用户可以直接通过Kubelet
组件获取给节点上容器相关监控指标; - 用户应用(Pod):
Pod
中会包含一组容器,它们一起工作,并且对外提供一个(或者一组)功能。如果用户部署的应用程序内置了对Prometheus
的支持,那么我们还应该采集这些Pod
暴露的监控指标; - Kubernetes组件:获取并监控
Kubernetes
核心组件的运行状态,确保平台自身的稳定运行。
2.3.2.2 黑盒层控制面
而在黑盒监控层面,则主要需要关注以下:
- 内部服务负载均衡(Service):在集群内,通过
Service
在集群暴露应用功能,集群内应用和应用之间访问时提供内部的负载均衡。通过Blackbox Exporter
探测Service
的可用性,确保当Service
不可用时能够快速得到告警通知; - 外部访问入口(Ingress):通过
Ingress
提供集群外的访问入口,从而可以使外部客户端能够访问到部署在Kubernetes
集群内的服务。因此也需要通过Blackbox Exporter
对Ingress
的可用性进行探测,确保外部用户能够正常访问集群内的功能;
03 搭建本地Kubernetes集群
3.1 安装Minikube
在本地通过工具Minikube
(https://github.com/kubernetes/minikube)搭建一个本地的Kubernetes
测试环境。Minikube
会在本地通过虚拟机运行一个单节点的Kubernetes
集群,可以方便用户或者开发人员在本地进行与Kubernetes
相关的开发和测试工作。
安装MiniKube
的方式很简单,对于Mac
用户可以直接使用Brew
进行安装(其它操作系统用户,可以查看Minikube
项目的官方说明文档进行安装即可):
brew install minikube
3.2 启动
启动的时候可能会报错,
Exiting due to RSRC_INSUFFICIENT_CORES: Requested cpu count 2 is greater than the available cpus of 1
解决方案参考(我是调整了docker desktop的cpu核数为2的):https://stackoverflow.com/questions/71207905/minkube-start-gives-error-exiting-due-to-rsrc-insufficient-cores-is-it-poss
因为mac
上已经安装了docker desktop
,所以不需要额外再安装Virtualbox
,直接选择Docker
驱动,使用如下命令启动:
minikube start --driver=docker • 1
如果一直卡在Pulling base image… ,则按顺序执行如下命令:
minikube delete minikube start --image-mirror-country='cn'
耐心等待。
在Docker Desktop
,可以看到已经启动容器:
备注:可以使用
minikube config set driver docker
命令来设置docker为默认驱动。
3.3 dashboard管理界面
MiniKube
会自动配置本机的kubelet
命令行工具,用于与对集群资源进行管理。同时Kubernetes
也提供了一个Dashboard
管理界面,在MiniKube
下可以通过以下命令打开:
minikube dashboard • 1
然后就会默认浏览器打开:
3.4 MiniKube基础命令
1.查看minikube的状态
minikube status
2.关闭cluster
minikube stop
3.删除cluster
minikube delete
04 Kubernetes部署应用程序
Kubernetes
环境准备完成后,就可以开始尝试在Kubernetes
下尝试部署一个应用程序。Kubernetes
中管理的所有资源都可以通过YAML
文件进行描述。
如下所示,本地创建了一个名为nginx-deploymeht.yml
文件:
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80
上传yml文件:
- 在该
YAML
文件中,我们定义了需要创建的资源类型为Deployment
,在metadata
中声明了该Deployment
的名称以及标签。 spec
中则定义了该Deployment
的具体设置,通过replicas
定义了该Deployment
创建后将会自动创建3
个Pod
实例,运行的Pod
以及进行则通过template
进行定义。
在命令行中使用,如下命令:
kubectl create -f nginx-deploymeht.yml • 1
在未指定命名空间的情况下,kubectl默认关联default命名空间。由于这里没有指定Namespace,该Deployment将会在默认的命令空间default中创建。 通过kubectl get命令查看当前Deployment的部署进度
# 查看Deployment的运行状态 $ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 3 3 3 3 1m # 查看运行的Pod实例 $ kubectl get pods NAME READY STATUS RESTARTS AGE nginx-deployment-6d8f46cfb7-5f9qm 1/1 Running 0 1m nginx-deployment-6d8f46cfb7-9ppb8 1/1 Running 0 1m nginx-deployment-6d8f46cfb7-nfmsw 1/1 Running 0 1m
为了能够让用户或者其它服务能够访问到Nginx实例,这里通过一个名为nginx-service.yml的文件定义Service资源:
kind: Service apiVersion: v1 metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 type: NodePort
默认情况下,Service资源只能通过集群网络进行访问(type=ClusterIP)。这里为了能够直接访问该Service,需要将容器端口映射到主机上,因此定义该Service类型为NodePort。
创建并查看Service资源:
$ kubectl create -f nginx-service.yml service "nginx-service" created $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 131d nginx-service NodePort 10.104.103.112 <none> 80:32022/TCP 10s
通过nginx-server映射到虚拟机的32022端口,就可以直接访问到Nginx实例的80端口:
部署完成后,如果需要对Nginx实例进行扩展,可以使用:
$ kubectl scale deployments/nginx-deployment --replicas=4 deployment "nginx-deployment" scaled
通过kubectl命令还可以对镜像进行滚动升级:
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1 deployment "nginx-deployment" image updated $ kubectl get pods NAME READY STATUS RESTARTS AGE nginx-deployment-58b94fcb9-8fjm6 0/1 ContainerCreating 0 52s nginx-deployment-58b94fcb9-qzlwx 0/1 ContainerCreating 0 51s nginx-deployment-6d8f46cfb7-5f9qm 1/1 Running 0 45m nginx-deployment-6d8f46cfb7-7xs6z 0/1 Terminating 0 2m nginx-deployment-6d8f46cfb7-9ppb8 1/1 Running 0 45m nginx-deployment-6d8f46cfb7-nfmsw 1/1 Running 0 45m
如果升级后服务出现异常,那么可以通过以下命令对应用进行回滚:
$ kubectl rollout undo deployment/nginx-deployment deployment "nginx-deployment"
Kubernetes依托于Google丰富的大规模应用管理经验。通过将集群环境抽象为一个统一调度和管理的云"操作系统,视容器为这个操作中独自运行的“进程”,进程间的隔离通过命名空间(Namespace)完成,实现了对应用生命周期管理从自动化到自主化的跨越。