prometheus监控k8s集群

1.整体概述

本文主要讲述如何使用prometheus,结合kube-state-metrics,cAdvisor,Grafana对k8s集群进行监控和报警,和监控大盘的整体展示。

2.环境描述

  • Kubernetes:v1.12.5
  • Prometheus:v2.3.1
  • kube-state-metrics:v1.3.1(收集k8s集群内资源对象数据)
  • cAdvisor(已经在k8s内部集成,不需要重新安装,收集资源使用情况)
  • Grafana:v5.3.4

3.监控组件部署

3.1 kube-state-metrics部署

kube-state-metrics安装有以下配置文件,可以把kube-state-metrics-deployment.yaml里面的镜像路径改成内网的镜像路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#把配置文件都放在kube-state-metrics,执行这个命令即可部署
kubectl -f kube-state-metrics/
#kube-state-metrics目录里面的配置信息
kube-state-metrics
├── kube-state-metrics-cluster-role-binding.yaml
├── kube-state-metrics-cluster-role.yaml
├── kube-state-metrics-deployment.yaml
├── kube-state-metrics-role-binding.yaml
├── kube-state-metrics-role.yaml
├── kube-state-metrics-service-account.yaml
└── kube-state-metrics-service.yaml

#查看kube-state-metrics是否已经起来
kubectl get pod -n kube-system -o wide |grep "kube-state-metrics"
#如果启动部署成功,信息如下:
kube-state-metrics-7fd5dcc9b6-kpxmm 2/2 Running 4 526d 10.244.3.39 wx-2-centos53 <none>

k8s 1.13.4升级到1.14.6

1.镜像准备

镜像准备(注意,提前在所有节点都下载好镜像,不然coredns kube-proxy 这些pod会自动安装安装不上 )

master节点粘贴下面脚本,下载镜像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
registry_host=reg.qingye.info
version=v1.14.6
pause_version=3.1
etcd_version=3.3.10
coredns_version=1.3.1
#镜像下载
docker pull $registry_host/library/kube-apiserver:$version
docker pull $registry_host/library/kube-controller-manager:$version
docker pull $registry_host/library/kube-scheduler:$version
docker pull $registry_host/library/kube-proxy:$version
docker pull $registry_host/library/pause:$pause_version
docker pull $registry_host/library/etcd:$etcd_version
docker pull $registry_host/library/coredns:$coredns_version
#镜像打tag
docker tag $registry_host/library/kube-apiserver:$version k8s.gcr.io/kube-apiserver:$version
docker tag $registry_host/library/kube-controller-manager:$version k8s.gcr.io/kube-controller-manager:$version
docker tag $registry_host/library/kube-scheduler:$version k8s.gcr.io/kube-scheduler:$version
docker tag $registry_host/library/kube-proxy:$version k8s.gcr.io/kube-proxy:$version
docker tag $registry_host/library/pause:$pause_version k8s.gcr.io/pause:$pause_version
docker tag $registry_host/library/etcd:$etcd_version k8s.gcr.io/etcd:$etcd_version
docker tag $registry_host/library/coredns:$coredns_version k8s.gcr.io/coredns:$coredns_version

node节点粘贴下面脚本,下载镜像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
registry_host=reg.qingye.info
version=v1.14.6
pause_version=3.1
etcd_version=3.3.10
coredns_version=1.3.1
#镜像下载
docker pull $registry_host/library/kube-proxy:$version
docker pull $registry_host/library/pause:$pause_version
docker pull $registry_host/library/etcd:$etcd_version
docker pull $registry_host/library/coredns:$coredns_version
#镜像打tag
docker tag $registry_host/library/kube-proxy:$version k8s.gcr.io/kube-proxy:$version
docker tag $registry_host/library/pause:$pause_version k8s.gcr.io/pause:$pause_version
docker tag $registry_host/library/etcd:$etcd_version k8s.gcr.io/etcd:$etcd_version
docker tag $registry_host/library/coredns:$coredns_version k8s.gcr.io/coredns:$coredns_version

利用LXCFS提升容器资源可见性

由于默认情况下容器挂载的是宿主机的硬件配置信息,导致有些应用根据这些信息来决定启动内存等的大小,导致应用内存溢出等问题。

LXCFS简介

社区中常见的做法是利用 lxcfs来提供容器中的资源可见性。lxcfs 是一个开源的FUSE(用户态文件系统)实现来支持LXC容器,它也可以支持Docker容器。

LXCFS通过用户态文件系统,在容器中提供下列 procfs 的文件。

1
2
3
4
5
6
/proc/cpuinfo
/proc/diskstats
/proc/meminfo
/proc/stat
/proc/swaps
/proc/uptime

LXCFS的示意图如下:

LXCFS的示意图

比如,把宿主机的 /var/lib/lxcfs/proc/memoinfo 文件挂载到Docker容器的/proc/meminfo位置后。容器中进程读取相应文件内容时,LXCFS的FUSE实现会从容器对应的Cgroup中读取正确的内存限制。从而使得应用获得正确的资源约束设定。

安装lxcfs ,先安装需要使用的依赖包:

yum install http://mirror.centos.org/centos/7/os/x86_64/Packages/fuse-libs-2.9.2-10.el7.x86_64.rpm

用deamonset方式在每个节点启动一个lxcfs,lxcfs-daemonset.yaml配置如下:

nginx-ingress-controller部署

1.打标签

由于nginx要部署到指定节点上,所以需要对node打个label,通过nodeSelector调度到节点上,同时要确保部署节点主机的80、443、18080、10254端口没有被占用。
kubectl label node ss-1-centos221 nginx-ingress=nginx
kubectl label node ss-1-centos221-2 nginx-ingress=nginx

2.准备nginx-ingress-controller部署文件

2.1 nginx-ingress-controller-rbac.yaml :设置rabc权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-ingress-serviceaccount
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: nginx-ingress-clusterrole
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- "extensions"
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- "extensions"
resources:
- ingresses/status
verbs:
- update
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: nginx-ingress-role
namespace: kube-system
rules:
- apiGroups:
- ""
resources:
- configmaps
- pods
- secrets
- namespaces
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
resourceNames:
# Defaults to "<election-id>-<ingress-class>"
# Here: "<ingress-controller-leader>-<nginx>"
# This has to be adapted if you change either parameter
# when launching the nginx-ingress-controller.
- "ingress-controller-leader-nginx"
verbs:
- get
- update
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: nginx-ingress-role-nisa-binding
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: nginx-ingress-role
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: nginx-ingress-clusterrole-nisa-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nginx-ingress-clusterrole
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: kube-system

k8s+dubbo架构集群内外网络通讯解决方案

1.问题

k8s有自己的一套网络管理机制,集群内的容器和容器之间是可以相互通信的。

但是在容器化升级改造的过程中,不可能一步到位的将所有的服务全部迁移到k8s的容器当中来,毕竟新的技术在没有经过实践趟坑时,肯定不能轻易的全面铺开升级。

那么就涉及到集群外的服务访问集群内的服务,集群内容器中的ip都是k8s管理的IP,dubbo服务注册的也是获取的容器内分配的IP。

比如宿主机ip是10.201.7.xx,容器内的ip就是172.66.4.x。群外的和宿主主机同网段的服务通过拿到dubbo的注册的172.66.4.x也根本没法访问容器内的dubbo服务。

2.分析

k8s是通过Service来暴露集群内的服务,假如dubbo服务注册的是Service暴露的端口和宿主的IP那么集群外的服务就可以直接访问集群内容器中的服务了。

该方案主要有两个难点:

1.如何获取Service暴露的端口和宿主机的IP注入到POD环境变量;

2.Dubbo服务如何从环境变量获取IP和端口注册到ZK;

关于难点1:

通过downward-api的方式向Pod内注入NodeIP的env;

通过给Pod注入env的方式将NodePort注入到Pod内;(要求先创建Service)

关于难点2:

Dubbo在启动阶段提供两对系统属性,用于设置外部通信的IP和端口地址。

DUBBO_IP_TO_REGISTRY — 注册到注册中心的IP地址
DUBBO_PORT_TO_REGISTRY — 注册到注册中心的端口
DUBBO_IP_TO_BIND — 监听IP地址
DUBBO_PORT_TO_BIND — 监听端口

深刻理解Docker镜像大小

1.docker镜像分析

是否还记得第一个接触Docker的时候,你从Docker Hub下拉的那个镜像呢?在那个处女镜像的基础上,你运行了容器生涯的处女容器。镜像的基石作用已经很明显,在Docker的世界里,可以说是:No Image,No Container。

再进一步思考Docker镜像,大家可能很快就会联想到以下几类镜像:

1.系统级镜像:如Ubuntu镜像,CentOS镜像以及Debian容器等;

2.工具栈镜像:如Golang镜像,Flask镜像,Tomcat镜像等;

3.服务级镜像:如MySQL镜像,MongoDB镜像,RabbitMQ镜像等;

4.应用级镜像:如WordPress镜像,DockerRegistry镜像等。

镜像林林总总,想要运行Docker容器,必须要有Docker镜像;想要有Docker镜像,必须要先下载Docker镜像;既然涉及到下载Docker镜像,自然会存在Docker镜像存储。谈到Docker镜像存储,那我们首先来聊聊Docker镜像大小方面的知识。

以下将从三个角度来分析Docker镜像的大小问题:Dockerfile与镜像、联合文件系统以及镜像共享关系。

Dockerfile与镜像
Dockerfile由多条指令构成,随着深入研究Dockerfile与镜像的关系,很快大家就会发现,Dockerfile中的每一条指令都会对应于Docker镜像中的一层。

继续以如下Dockerfile为例:

1
2
3
4
FROM ubuntu:14.04
ADD run.sh /
VOLUME /data
CMD ["./run.sh"]

k8s常见问题解决

1.基础镜像制作规范和使用

1.1 时区修改
官网下载centos镜像默认时区是国外的时区,需要把它修改成上海时区。运维提供提一个基础的镜像给业务部门下载使用。

1.2 规范docker运行程序的用户
基于安全和规范的考虑,docker统一使用一个uid为1001的,用户名为pub的普通账号运行程序,需要在镜像和容器的宿主机上面同时新建。这个也是运维在初始化基础镜像和容器宿主机上面统一创建。

1.3 规范每个容器的cpu和内存(每个容器分配1核2G内存,视情况而定)

2.镜像下载策略

2.1 默认的镜像拉取策略是“IfNotPresent”,在镜像已经存在的情况下,kubelet将不在去拉取镜像。 如果总是想要拉取镜像,必须设置拉取策略为“Always”或者设置镜像标签为“:latest”。

如果没有指定镜像的标签,它会被假定为“:latest”,同时拉取策略为“Always”。

3.增加k8s各个命名空间的服务账号 default 的自定义权限(RABC)

首先,了解下什么是RABC:

基于角色的访问控制(Role-Based Access Control, 即”RBAC”)使用”rbac.authorization.k8s.io” API Group实现授权决策,允许管理员通过Kubernetes API动态配置策略。

在RBAC API中,一个角色包含了一套表示一组权限的规则。 权限以纯粹的累加形式累积(没有”否定”的规则)。 角色可以由命名空间(namespace)内的Role对象定义,而整个Kubernetes集群范围内有效的角色则通过ClusterRole对象实现

比如授予default命名空间的default ServiceAccount账号能够”get”, “watch”, “list”, “patch” default 命名空间里面的pod资源

3.1 定义role,一个Role对象只能用于授予对某一单一命名空间中资源的访问权限。 以下示例描述了”default”命名空间中的一个Role对象的定义,用于授予对pod的读访问权限:

1
2
3
4
5
6
7
8
9
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""] # 空字符串""表明使用core API group
resources: ["pods"]
verbs: ["get", "watch", "list", "patch"]

k8s专题[10.使用Spinnaker持续发布应用]

本节介绍如何使用spinnaker的持续发布k8s的应用

1.首先使用spinnaker创建一个nginxdemo 的应用,再在nginxdemo应用里面创建 Pipeline。进入nginxdemo 详情页面,点击 “PIPELINES”,目前是没有任何信息的,点击 “+ Create”,弹框中选择类型为 Pipeline,输入流程名称,这里我命名为 nginxdemo-pipe。因为第一次创建,下边 “Copy From” 选择没出来,后续在创建时,我们也可以通过 “Copy From” 方式选择已存在的 Pipeline,非常方便就复制了一个一样配置的流程。创建完毕后,就会出现详细配置 Pipeline State 的页面了

图1

2.配置 Configuration 项

刚开始这里只有一个 Configuration 选项,可以配置 Automated Triggers、Parameters、Notifications 等,这里说下 Automated Triggers 和 Parameters 这两个非常有用,我们可以将此视为 Pipeline 启动前的一些初始化配置,比如启动需要的参数配置、自动触发配置等,为后续各阶段提供必要的信息。
Automated Triggers 自动触发,它提供 7 种类型的触发方式:

  • CRON:调度触发,可以执行一个 cron 调度任务来定时任务触发该流程。
  • Git:当执行 Git push 操作时,触发该流程
  • Jenkins:监听 Jenkins 的某一个 Job
  • Travis:监听 Travis 的某一个 Job
  • Pipeline:监听另一个 Pipeline 执行
  • Pub/Sub:当接受到 pubsub 消息时触发
  • Docker Registry:当 image 更新时触发。

基本能满足我们日常持续集成或交付的需求,当然每一个类型都需要配置相应的参数,比如 Cron 类型,需要配置执行频率、启动时间等。下图我们选择Docker Registry作为触发类型

k8s专题[9.基于Jenkins和Spinnaker的CI/CD流程]

流程图

基于Jenkins和Spinnaker的CI/CD流程

流程说明:
1.用户向Gitlab提交代码,代码中包含Dockerfile
2.将代码提交到远程仓库
3.Gitlab提交触发Jenkins自动构建
4.Jenkins的CI流水线自动编译代码并打包成docker镜像推送到Harbor镜像仓库
5.更新Ingress的配置,根据新部署的应用的名称,在ingress的配置文件中增加一条路由信息(不是新业务不用更改此配置)
6.Jenkins构建完成可触发Spinnaker的自动发布流程,或者手动触发spinnaker发布。
7.Spinnaker会根据发布流程更新kubernetes YAML配置文件
8.Spinnaker调用kubernetes的API,部署应用

k8s专题[8.spinnaker基本介绍]

1.概念

Spinnaker 是 Netflix 的开源项目,是一个持续交付平台,它定位于将产品快速且持续的部署到多种云平台上。Spinnaker 通过将发布和各个云平台解耦,来将部署流程流水线化,从而降低平台迁移或多云品台部署应用的复杂度,它本身内部支持 Google、AWS EC2、Microsoft Azure、Kubernetes和OpenStack 等云平台,并且它可以无缝集成其他持续集成(CI)流程,如 git、Jenkins、Travis CI、Docker registry、cron 调度器等。简而言之,Spinnaker是致力于提供在多种平台上实现开箱即用的集群管理和部署功能的平台。

2.功能

2.1:集群管理主要用于管理云上的资源,它分为以下几个块

  • Server Group:服务组,是资源管理单位,识别可部署组件和基础配置设置,它并且关联了一个负载均衡器和安全组,当部署完毕后,服务组就相当于一组运行中的软件实例集合,如(VM 实例,Kubernetes pods)。
  • Cluster:集群,由用户定义的,对服务组的逻辑分组。
  • Applications:应用,是对集群的逻辑分组。
  • Load Balancer:负载均衡,用于将外部网络流量重定向到服务组中的机器实例,还可以指定一系列规则,用来对服务组中的机器实例做健康监测。
  • Security Group:安全组,定义了网络访问权限,由IP、端口和通信协议组成的防火墙

2.2:部署管理功能用于创建一个持续交付流程,它可分为管道和阶段两大部分

  • 管道 部署管理的核心是管道,在Spinnaker的定义中,管道由一系列的阶段(stages)组成。管道可以人工触发,也可以配置为自动触发,比如由 Jenkins Job 完成时、Docker Images 上传到仓库时,CRON 定时器、其他管道中的某一阶段。同时,管道可以配置参数和通知,可以在管道一些阶段上执行时发送邮件消息。Spinnaker 已经内置了一些阶段,如执行自定义脚本、触发 Jenkins 任务等。
  • 阶段 阶段在 Spinnaker 中,可以作为管道的一个自动构建模块的功能组成。我们可以随意在管道中定义各个阶段执行顺序。Spinnaker 提供了很多阶段供我们选择使用,比如执行发布(Deploy)、执行自定义脚本 (script)、触发 Jenkins 任务 (jenkins)等,功能很强大。
  • 部署策略 Spinnaker 支持精细的部署策略,比如 红/黑(蓝/绿)部署,多阶段环境部署,滚动红/黑策略,canary 发布等。用户可以为每个环境使用不同部署策略,比如,测试环境可以使用红/黑策略,生产环境使用滚动红/黑策略,它封装好了必须的步骤,用户不需要复杂操作,就可以实现企业级上线。

3.Spinnaker 架构所依赖的各个组件


:D 一言句子获取中...