K8S学习笔记

一、核心介绍

1.1、发展历程

  1. Infrastructure as a Service:基础设施服务
  2. PlatForm as a service:平台即服务 -> 下一代Docker
  3. Software as a service:软件即服务

1.2 、分布式资源管理

1.2.1、Apace MESOS

twitter -> 后来迁移
Mesos是Apache下的开源分布式资源管理框架,它被称为是分布式系统的内核。-> 抽象资源+调度任务。

  1. 支持数万个节点的大规模场景
  2. 支持多种应用框架,包括Marathon、Singularity、Aurora等;
  3. 支持HA(基于ZooKeeper实现)
  4. 支持Docker、LXC等容器机制进行任务隔离;
  5. 提供了多个流行语言的API,包括Python、Javaden
  6. 自带了简洁易用的WebUI,方便用户直接进行操作

MESOS架构图

Mesos采用了经典的“主-从”架构,其中主节点(管理节点)可以使用Zookeeper来做HA。Mesos master 服务奖运行在主节点上,Mesos slave 服务则需要运行在各个计算任务节点上。负责完成具体任务的应用框架,与Mesos master进行交互,来申请资源。
Mesos有三个基本的组件:管理服务(master)、任务服务(slave)以及应用框架(framework)。

  1. 管理服务(master):跟大部分分布式系统中类似,主节点起到管理作用,将看到全局的信息,负责不同应用框架之间的资源调度和逻辑控制。应用框架需要注册到管理服务上才能被使用。用户和应用需要通用主节点提供的API来获取集群状态和操作集群资源。
  2. 任务服务(slave):负责汇报本从节点上的资源状态(空闲资源、运行状态等等)给主节点,并负责隔离本地资源来执行主节点分配的具体任务。隔离机制目前包括各种容器机制,包括LXC、Docker等。
  3. 应用框架(framework):应用框架是实际干活的,包括连个主要组件:
    1. 调度器:注册到主机诶单,等待分配资源;
    2. 执行器:在从节点上执行框架指定的任务(框架也可以使用Mesos自带的执行器,包括shell脚本执行器和Docker执行器)
    3. 应用框架可以分两种:一种是对资源的需求会扩展(比如Hadoop、Spark等),申请后还可能调整;另一种是对资源的需求将会固定(MPI等),一次申请即可。

调度:
对于一个资源调度框架来说,最核心的就是调度机制,怎么能快速高效地完成对某个应用框架资源的分配,是核心竞争力所在。最理想情况下(大部分时候都无法实现),最好是能猜到应用们的实际需求,实现最大化的资源使用率。Mesos为了实现尽量优化的调度,采取了两层(two-layer)的调度算法
调度的基本思路很简单,master先全局调度一大块资源给某个framework,framework自己在实现内部的细粒度调度,决定那个任务用多少资源。两层调度简化了Mesos master自身的调度过程,通过将复杂的细粒度调度交由framework实现,避免了Mesos master成为性能的瓶颈。
调度过程:调度通过offer发送的方式进行交互。一个offer是一组资源例如<1 CPU ,2GB Mem>>。

基本调度过程如下:

  1. Slave节点会周期性汇报自己可用的资源给master;某个时候,master收到应用框架发来的资源请求,根据调度策略,计算出来一个资源offer给framework;framework收到offer后可以决定要不要,如果接受的话,返回一个描述,说明自己希望如何使用和分配这些资源来运行某些任务(可以说明只希望使用部分资源,则多出来的会被master收回);
  2. master则根据framework答复的具体分配情况发送给slave,以使用framework的executor来按照分配的资源策略执行任务。

具体给出一个例子:
某从节点想主节点汇报自己有<4 CPU , 8 GB Mem>的空闲资源,同时,主节点看到某个应用框架请求<3 CPU , 6 GB Mem>,就创建一个offer<slave #1, 4 CPU, 8GB> 把满足的资源发给应用框架。应用框架(的调度器)收到offer后觉得可以接受,就恢复主节点,并告诉主机节点希望运行两个任务:一个占用<1CPU ,2GB Mem>, 一个占用<2 CPU , 4GB Mem>。主节点收到任务信息后分配任务到从节点上运行(实际上是应用框架的执行器来负责执行任务)。任务执行结束后资源可以被释放出来。剩余则资源还尅继续分配给其他应用框架或任务。应用框架在收到offer后,如果offer不满足自己的偏好(例如希望继续使用上次的slave)则可以选择拒绝offer,等待master发送新的offer过来。另外可以通过过滤机制加快资源的分配过程。

1.2.2、Docker Swarm

Docker Swarm –> 只提供Docker组件
Swarm是Docker公司推出的用来管理docker集群的平台,几乎全部用GO语言来完成的开发的,代码开源在https://github.com/docker/swarm, 它是将一群Docker宿主机变成一个单一的虚拟主机,Swarm使用标准的Docker API接口作为其前端的访问入口,换言之,各种形式的DockerClient都可以直接与其进行通讯,方便用户部署集群主机服务。

Docker Compose 在单一主机上面部署服务
Docker Swarm 多台主机上面管理服务

Swarm deamon只是一个调度器(Scheduler)加路由器(router),Swarm自己不运行容器,它只是接受Docker客户端发来的请求,调度适合的节点来运行容器,这就意味着,即使Swarm由于某些原因挂掉了,集群中的节点也会照常运行,放Swarm重新恢复运行之后,他会收集重建集群信息。

Docker Client使用Swarm对 集群(Cluster)进行调度使用,Swarm是典型的master-slave结构,通过发现服务来选举manager。manager是中心管理节点,各个node上运行agent接受manager的统一管理,集群会自动通过Raft协议分布式选举出manager节点,无需额外的发现服务支持,避免了单点的瓶颈问题,同时也内置了DNS的负载均衡和对外部负载均衡机制的集成支持

  1. Swarm:集群管理和编排使用的是SwarmKit

  1. Node:代表集群中的一个实例信息(一个物理机),上面可以部署多个容器

  1. Service:表示Node中的一个服务信息,承载在一个容器中

  1. Task:表示一个docker容器中实际执行的命令(分配任务)

1.2.2.2、Swarm 集群模式特性

  1. 批量创建服务:创建一个overlay的网络,用来保证在不同主机上的容器网络互通的网络模式
  2. 强大的集群的容错性 && 服务节点的可扩展性:
    容器副本中的其中某一个或某几个节点宕机后,cluster会根据自己的服务注册发现机制,以及之前设定的值–replicas n,在集群中剩余的空闲节点上,重新拉起容器副本。整个副本迁移的过程无需人工干预,迁移后原本的集群的load balance依旧好使!不难看出,docker service其实不仅仅是批量启动服务这么简单,而是在集群中定义了一种状态。Cluster会持续检测服务的健康状态。
    1. 复制服务(–replicas n):在一个节点下Node下进行容器的复制操做
    2. 全局复制服务(–mode=global):将一个容器复制发布到全局的节点中
  3. 调度机制
    由cluster的server端去选择在哪个服务器节点上创建并启动一个容器实例的动作。它是由一个装箱算法和过滤器组合而成。每次通过过滤器(constraint)启动容器的时候,swarm cluster 都会调用调度机制筛选出匹配约束条件的服务器,并在这上面运行容器。

集群创建过程:
1)发现Docker集群中的各个节点,收集节点状态、角色信息,并监视节点状态的变化
2)初始化内部调度(scheduler)模块
3)创建并启动API监听服务模块

1.2.3、Kubernetes

Google –> 10年容器基础架构Borg 2014开源–> 使用GO重构[[GO基础学习]]重构K8S
Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快速增长的生态,其服务、支持和工具的使用范围相当广泛。方便伸缩扩容

  • 服务发现和负载均衡

    Kubernetes 可以使用 DNS 名称或自己的 IP 地址来曝露容器。 如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。

  • 存储编排

    Kubernetes 允许你自动挂载你选择的存储系统,例如本地存储、公共云提供商等。

  • 自动部署和回滚

    你可以使用 Kubernetes 描述已部署容器的所需状态, 它可以以受控的速率将实际状态更改为期望状态。 例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。

  • 自动完成装箱计算

    Kubernetes 允许你指定每个容器所需 CPU 和内存(RAM)。 当容器指定了资源请求时,Kubernetes 可以做出更好的决策来为容器分配资源。

  • 自我修复

    Kubernetes 将重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器, 并且在准备好服务之前不将其通告给客户端。

  • 密钥与配置管理

    Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。

  • 弹性伸缩

特点:

  1. 采用GO开发轻量级,消耗资源小
  2. 开源
  3. 弹性伸缩
  4. 内部实现自动负载均衡:采用IPVS -> [[IPVS(IP Virtual Server) && LVS (Linux Virtual Server)]]

1.2.4、区别

  1. 可伸缩性 && 弹性
    1. Mesos对于运行着大规模集群的公司来说是最好的选择,在模拟测试中,其最高可以运行5万多个节点
    2. Kubernetes和Swarm都被限制在1000个节点(大约5万个容器)。同时Mesos在大规模解决方案实践上拥有强大的话语权,如Twitter这样的大公司都在使用。

Swarm:适合中小型系统,在这个范畴它的价值和可扩展性最好
Kubernetes:适合中等规模高度冗余的系统
Mesos:目前最稳定的平台,适合大规模系统

#todo

  • 其他区别

二、K8S 组件 && 结构

2.1、核心概念

2.1.1、NODE

Node是Pod真正运行的主机,可以物理机,也可以是虚拟机。为了管理Pod,每个Node节点上至少要运行container runtime(容器运行环境:比如docker或者rkt)、kubelet和kube-proxy服务。

  • 地址:包括hostname、外网IP和内网IP
  • 条件(Condition):包括OutOfDisk、Ready、MemoryPressure和DiskPressure
  • 容量(Capacity):Node上的可用资源,包括CPU、内存和Pod总数
  • 基本信息(Info):包括内核版本、容器引擎版本、OS类型等
    如果node 被删除,所拥有的pod会自动分流到其他的node,但是存在特殊的无法被分流的pod

2.1.2、POD

基本概念

POD的概念类比:

为什么容器等于进程?[[Docker容器-单进程]]
因此在K8S中提供一个POD来运行多个进程,满足多进程应用的使用。因此POD是一个逻辑上的概念,物理上实际上是四个容器,并且一个POD中共享了一揽子资源。

为什么Pod必须是原子调度单位?[[为什么POD是原子调度单位]]

  1. 是一个K8S中的最小的部署单元、管理单元是一组容器的集合
  2. 一个POD中可以有多个容器Container
  3. 一个POD之间的容器可以相互通讯,共享网络
  4. 生命周期是短暂的,服务器重启会丢失
  5. POD与POD之间隔离

实现原理

POD的实现原理是什么?[[POD的实现原理]]

2.1.3、Controller

  1. 确保预期POD中副本数量
  2. 无状态^1应用部署
  3. 有状态^2应用部署
  4. 所有的NODE都运行相同的POD
  5. 一次性任务和定时任务
  6. 负责创建

    创建POD进行部署

2.1.4、Service

  1. 定义一组POD的访问方法

    通过Service统一接口进行访问

2.1.5、Volume

  1. 声明 POD中可访问的文件目录
  2. 可以挂载到一个POD中一个或者多个容器 的指定路径下
  3. 支持多种后端实际存储的抽象(本地存储、云存储、分布式……1)

2.1.6、Deployment

  1. 定义一组POD的副本数目版本等
  2. 通过控制器维护POD数目
    1. 自动恢复失败POD
  3. 通过控制器制定策略版本
    1. 滚动升级
    2. 重新生成
    3. 回滚

2.1.7、Service

用于将多个POD实例地址进行抽象,对外暴露一个服务端口地址
支持的访问方式实现:

  1. ClusterIp
  2. NodePort
  3. LoadBalancer

2.1.9、NameSpaces

  1. 集群内部的逻辑隔离机制(资源,鉴权)
  2. 每个资源都是一个NameSpace
  3. 同一个NameSpace中名称不能重复,不同可重名

2.1.8、核心架构

架构举例:

  • Master:主节点
    • API Server:集群入口RestFul风格,处理到请求,交给ETCD存储
    • ControllerManager:处理集群常规后台任务,一个资源对应一个控制器
    • Scheduler:节点调度器,选择不同NODE节点进行选择调度
    • ETCD:K/V 存储数据,集群相关基本数据
  • Node:工作节点
    • Kubelet:master 派到一个容器节点管理节点的代理
    • Kube-Proxy:网络之间的维护代理,实现负载均和一级网络上代理

实际组件交互例子:

每一个厂都有一个Kubelet代理,负责当前应用启停和销毁,当出现问题的时候由Kubelet进行处理,回报信息给秘书(ApiServer)-> Controller - manager(领导人-决定)
-> 交给决策者进行处理(动态调度进行调度处理)
    -> 存储决策文件
    -> 分配决策
-> 存储决策文件到档案库ETCD

-> ApiServer进行通知Kubelet进行处理
当应用构建结束之后,应用之间相互调用由Kube-Proxy(门卫)进行统一处理,打通整个服务,门卫之间信息相互同步。
最终实际上整个集群由KubeCtl(程序员命令)进行直接控制,启动开启集群,这个命令实质上也是发送个ApiServer进行实际处理。

2.2、ApI

日常使用的APi都使用HTTP与k8s交互

API-Label

label-selecter通过Label对k8s中的pod进行筛选:

2.3、搭建K8S集群

[[K8S集群搭建]]

搭建工具:

  1. Kubeadmin:K8S部署工具,使用Kubeadm Init、Kubeadm Init
  2. 二进制包:手动部署每个组件

2.2.1、前置安装

  1. 一台或者多台系统
  2. 2G或者更多RAM
  3. CPU:2C或者更多
  4. 硬盘30G以上
  5. 机器间网络互通
  6. 必须访问外网
  7. 禁止SWAP分区
    1. 临时禁止: swapoff -a
    2. 永久关闭:vim /etc/fstab -> 注释掉最后一行Swap

2.2.2、KubeAdmin

是官方社区推出的快速部署KuberNetes集群工具,可以通过一下两个命令实现快速搭建。

2.2.2.1、操作系统安装

集群分配:
192.168.153.131 k8s_master
192.168.153.129 slave1
192.168.153.130 slave2
192.168.153.128 slave3
root账户密码为:
root : 123456789

  • 开启root [[Ubuntu开启Root远程访问]]
  • 关闭防火墙 yes
    1
    2
    3
    4
    5
    #关闭防火墙
    #临时
    systemctl stop firewalld
    #永久关闭
    systemctl disable firewalld

出现如下报错,请使用apt install -y firewalld

  • 关闭selinux How to disable/enable SELinux on Ubuntu 20.04 Focal Fossa Linux - Linux Tutorials - Learn Linux Configuration

    1. 安装: sudo apt install policycoreutils selinux-utils selinux-basics
      1. 激活:sudo selinux-activate
      2. 设置启用:sudo selinux-config-enforcing
      3. 重启系统
      4. 查看SELinux 状态
    2. 关闭:
      1. 打开:/etc/selinux/config
      2. 设置:SELINUX=disabled
      3. 重启
  • 关闭Swap yes

    1
    2
    3
    4
    # 临时
    swapoff -a
    # 永久关闭
    sed -ri 's/.*swap.*/#&/' /etc/fstab
  • 方便访问设置名称

    1
    2
    #设置主机名称
    hostnamectl set-hostname xxxx
  • 设置Host地址(只需要在Master中设置)

    1
    2
    3
    4
    5
    6
    cat >> /etc/hosts <<EOF
    192.168.153.131 k8s_master
    192.168.153.129 slave1
    192.168.153.130 slave2
    192.168.153.128 slave3
    EOF
  • 设置流量转发 yes

    1
    2
    3
    4
    5
    6
    7
    # 将桥接的IPv4流量传递到iptables的链
    cat > /etc/sysctl.d/k8s.conf << EOF
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    EOF
    # 生效
    sysctl --system
  • 设置同步时间 yes

    1
    2
    apt install ntpdate -y
    ntpdate time.windows.com
  • 安装Docker

    1
    2
    3
    4
    5
    #ubuntu
    curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

    #centos
    curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
  • Docker 加速 [[镜像加速]]

  • 换源 [[Ubuntu 换源]]

  • 设置开机自启动

    1
    systemctl enable docker && systemctl start docker
  • 重启Docker

    1
    systemctl restart docker

2.2.2.2、安装K8S

注意版本兼容性问题

2.2.2.2.1、前置安装

所有节点都进行安装

  1. 安装kubeletkubeadmkubect
    1. 安装证书工具:sudo apt-get install -y apt-transport-https ca-certificates curl
    2. 安装证书:sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
    3. 添加K8S软件源:echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
    4. 更新版:sudo apt-get update
    5. 安装K8S:apt install kubeadm=1.23.8-00 kubelet=1.23.8-00 kubectl=1.23.8-00
    6. 开机自启:systemctl enable kubelet
2.2.2.2.2、安装部署主节点
  1. 执行初始化init:
    1
    2
    3
    4
    5
    6
    7
    kubeadm init \
    --apiserver-advertise-address=(master节点ip) \
    --image-repository registry.aliyuncs.com/google_containers \
    --kubernetes-version v1.23.8 \
    --service-cidr=10.96.0.0/12 \
    --pod-network-cidr=10.244.0.0/16 \
    --ignore-preflight-errors=all
    成功提示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.153.131:6443 --token 080k86.3w1djwjhxe5q4l4p --discovery-token-ca-cert-hash sha256:8b82312bf868a68919b8de12cbbf7a97be20cd795d816332bcc9f3d81a0838d3

查看主节点工作情况kubeadm get nodes

2.2.2.2.2、安装部署从节点
  1. 在从节点中执行命令:kubeadm join 192.168.153.131:6443 --token 080k86.3w1djwjhxe5q4l4p --discovery-token-ca-cert-hash sha256:8b82312bf868a68919b8de12cbbf7a97be20cd795d816332bcc9f3d81a0838d3

    成功结果:

  2. 主节点中查看状态:

注:执行时候出现:


解决方案:执行kubeadm reset恢复设置,之后再次执行上述命令

2.2.2.2.3、安装网络插件

root执行:
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

插件可能因为网络原因执行失败,这里附上文件kube-flannel.yml,使用kubectl apply -f进行执行

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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
---

kind: Namespace

apiVersion: v1

metadata:

  name: kube-flannel

  labels:

    pod-security.kubernetes.io/enforce: privileged

---

kind: ClusterRole

apiVersion: rbac.authorization.k8s.io/v1

metadata:

  name: flannel

rules:

- apiGroups:

  - ""

  resources:

  - pods

  verbs:

  - get

- apiGroups:

  - ""

  resources:

  - nodes

  verbs:

  - list

  - watch

- apiGroups:

  - ""

  resources:

  - nodes/status

  verbs:

  - patch

---

kind: ClusterRoleBinding

apiVersion: rbac.authorization.k8s.io/v1

metadata:

  name: flannel

roleRef:

  apiGroup: rbac.authorization.k8s.io

  kind: ClusterRole

  name: flannel

subjects:

- kind: ServiceAccount

  name: flannel

  namespace: kube-flannel

---

apiVersion: v1

kind: ServiceAccount

metadata:

  name: flannel

  namespace: kube-flannel

---

kind: ConfigMap

apiVersion: v1

metadata:

  name: kube-flannel-cfg

  namespace: kube-flannel

  labels:

    tier: node

    app: flannel

data:

  cni-conf.json: |

    {

      "name": "cbr0",

      "cniVersion": "0.3.1",

      "plugins": [

        {

          "type": "flannel",

          "delegate": {

            "hairpinMode": true,

            "isDefaultGateway": true

          }

        },

        {

          "type": "portmap",

          "capabilities": {

            "portMappings": true

          }

        }

      ]

    }

  net-conf.json: |

    {

      "Network": "10.244.0.0/16",

      "Backend": {

        "Type": "vxlan"

      }

    }

---

apiVersion: apps/v1

kind: DaemonSet

metadata:

  name: kube-flannel-ds

  namespace: kube-flannel

  labels:

    tier: node

    app: flannel

spec:

  selector:

    matchLabels:

      app: flannel

  template:

    metadata:

      labels:

        tier: node

        app: flannel

    spec:

      affinity:

        nodeAffinity:

          requiredDuringSchedulingIgnoredDuringExecution:

            nodeSelectorTerms:

            - matchExpressions:

              - key: kubernetes.io/os

                operator: In

                values:

                - linux

      hostNetwork: true

      priorityClassName: system-node-critical

      tolerations:

      - operator: Exists

        effect: NoSchedule

      serviceAccountName: flannel

      initContainers:

      - name: install-cni-plugin

       #image: flannelcni/flannel-cni-plugin:v1.1.0 for ppc64le and mips64le (dockerhub limitations may apply)

        image: rancher/mirrored-flannelcni-flannel-cni-plugin:v1.1.0

        command:

        - cp

        args:

        - -f

        - /flannel

        - /opt/cni/bin/flannel

        volumeMounts:

        - name: cni-plugin

          mountPath: /opt/cni/bin

      - name: install-cni

       #image: flannelcni/flannel:v0.18.1 for ppc64le and mips64le (dockerhub limitations may apply)

        image: rancher/mirrored-flannelcni-flannel:v0.18.1

        command:

        - cp

        args:

        - -f

        - /etc/kube-flannel/cni-conf.json

        - /etc/cni/net.d/10-flannel.conflist

        volumeMounts:

        - name: cni

          mountPath: /etc/cni/net.d

        - name: flannel-cfg

          mountPath: /etc/kube-flannel/

      containers:

      - name: kube-flannel

       #image: flannelcni/flannel:v0.18.1 for ppc64le and mips64le (dockerhub limitations may apply)

        image: rancher/mirrored-flannelcni-flannel:v0.18.1

        command:

        - /opt/bin/flanneld

        args:

        - --ip-masq

        - --kube-subnet-mgr

        resources:

          requests:

            cpu: "100m"

            memory: "50Mi"

          limits:

            cpu: "100m"

            memory: "50Mi"

        securityContext:

          privileged: false

          capabilities:

            add: ["NET_ADMIN", "NET_RAW"]

        env:

        - name: POD_NAME

          valueFrom:

            fieldRef:

              fieldPath: metadata.name

        - name: POD_NAMESPACE

          valueFrom:

            fieldRef:

              fieldPath: metadata.namespace

        - name: EVENT_QUEUE_DEPTH

          value: "5000"

        volumeMounts:

        - name: run

          mountPath: /run/flannel

        - name: flannel-cfg

          mountPath: /etc/kube-flannel/

        - name: xtables-lock

          mountPath: /run/xtables.lock

      volumes:

      - name: run

        hostPath:

          path: /run/flannel

      - name: cni-plugin

        hostPath:

          path: /opt/cni/bin

      - name: cni

        hostPath:

          path: /etc/cni/net.d

      - name: flannel-cfg

        configMap:

          name: kube-flannel-cfg

      - name: xtables-lock

        hostPath:

          path: /run/xtables.lock

          type: FileOrCreate

查看当前节点pods状态 kubectl get pods -n kube-system
观察是否ready为全部上线,图例如下:

2.2.2.2.4、查看安装结果

kubectl get nodes

2.2.2.2.5、验证安装

创建一个Nginx集群:

  1. 执行命令:kubectl create deployment nginx --image=nginx
  2. 查看状态:kubectl get pod
    等待成为Running则执行下述,开启暴露端口:
    kubectl expose deployment nginx --port=80 --type=NodePort

查看状态:
kubectl get pod,svc

查看暴露的端口是,30612,从集群中任意节点都可以访问 -> 测试如下:

2.2.3、二进制包

未做,待更

2.2.4、总述

KubeAdmin:

  1. 安装虚拟机
  2. 更新软件源
  3. 配置运行环境
    1. 关闭防火墙
    2. 关闭Swap
    3. 关闭Selinux
    4. 设置Ipv4 -> iptables
    5. 设置host与主机名
    6. 时间同步
  4. 所有节点均安装 Docker、KubeAdm、Kubelet、KubeCtl
  5. 修改Docker镜像源

二进制:

三、核心组件

3.1、KubeCtl

是一个K8s集群的管理工具,实现对集群的基本管理和处理。
语法:kubectl command type name flags

  1. command:对资源的操做
    1. create
    2. get
    3. describe
    4. delete
  2. type:指定资源类型,大小写敏感
    1. pod
    2. pods
    3. node
    4. …..
  3. name:资源名称。大小写敏感,不加就是全部
    示例:kubectl get nodes slave1

kubectl get pod,svc:查看pod运行在线情况

kube get cs:查看健康状态

kubectl --help命令行工具 (kubectl) | Kubernetes

3.1.1、基础命令

3.1.2、部署和集群管理

3.1.3、故障调试

3.1.4、其他命令

3.2 Yaml文件(资源编排)

  • 使用空格做为缩进
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • 低版本缩进时不允许使用Tab 键,只允许使用空格
  • 使用#标识注释,从这个字符一直到行尾,都会被解释器忽略

3.2.1、KubeCtl create生成Yaml

kubectl create deployment web --image=nginx -o yaml --dry-run
生成文件如下:

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
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}

3.2.2、kubeCtl get导出Yaml文件

kubectl get deploy nginx -o=yaml > my.yaml

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
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2022-07-13T08:06:10Z"
generation: 1
labels:
app: nginx
name: nginx
namespace: default
resourceVersion: "4889"
uid: e235528a-958f-4b83-8205-cba3b0f0255d
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 1
conditions:
- lastTransitionTime: "2022-07-13T08:07:57Z"
lastUpdateTime: "2022-07-13T08:07:57Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2022-07-13T08:06:10Z"
lastUpdateTime: "2022-07-13T08:07:57Z"
message: ReplicaSet "nginx-8f458dc5b" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 1
replicas: 1
updatedReplicas: 1

3.3、POD

3.3.1、基本概念

  1. 是K8S中最小的部署单元
  2. K8S不会直接处理容器,实际上是管理POD并且一个POD是一组容器的集合。
  3. 一个POD中的每个容器都共享一个POD网络的命名空间(一个POD中网络共享)
  4. POD是短暂的,动态的
  5. 每个POD都包含一个根容器

3.3.2、特点

为什么管理的不是容器?
因为正常处理情况下:

  1. 容器使用Docker创建的,一个docker对应一个容器、一个单进程并且对应运行一个应用程序。
  2. docker进程是一个守护进程,一直监听活动。当一个docker中运行多个应用程序的时候不方便管理,一次docker容器中实际上是一个服务一个进程。
  3. POD是一个多进程的设计,可以同时运行多个应用程序。
  4. 一个POD多个容器,一个容器运行一个应用程序,因此POD是一个多线程容器。
  5. 亲密性
    1. POD存在为了亲密性交互,POD内部进行交互
    2. 网络之间的交互远程的调用
    3. 两个应用之间频繁调用。

3.3.3、Pod实现机制

3.3.3.1、共享网络
1. 容器之间相互隔离,通过namespace和group组进行隔离

多个容器在同一个namespace中就可以实现网络共享。
POD在创建过程中首先会创建一个根容器(Pause容器也叫Info容器)当你每创建一个用户业务
容器都会把用户容器加入到Info容器中,也就是变成了处于同一个名称空间,一个mac地址一个IP地址

yaml示例:

3.3.3.2、共享存储
1. 持久化数据类型:
    1.  日志数据
    2. 业务数据

共享存储由数据卷Volumn构成,通过数据卷进行持久化存储,映射数据/

yaml示例:

3.3.3.3、镜像拉取 imagePullPolicy
1. IfNotPresent:不存在的时候拉取(默认)
2. Always:每次创建POD都会自动重新拉取
3. Never:POD从不主动拉取,必须手动拉取

3.3.3.4、资源限制

Request:调度资源大小
Limit:最大大小
本身实际上是由Docker来限制资源的

3.3.3.5、POD 重启机制 restartPolicy
1. Always:容器终止后自动重启(适用于一般使用容器)
2. OnFailure:容器异常退出,状态码非零重启
3. Never:容器终止从不退出

3.3.3.6、健康检查

原始情况我们检测的是容器是否运行,但是比如Java发生OOM的时候,容器时正常的,但是业务不正常。因此需要从业务层面监控。
1. livenessProbe(存活检查):检查失败就杀掉容器,根据POD 的restartPolicy进行处理
2. readinessProbe(就绪检查):检查失败会从service endpoint中剔除

3.3.3.7、调度策略
3.3.3.7.1、创建POD

  1. Master 节点:
    1. create pod -> ApiServer ->存储到etcd
    2. Scheduler -> 监控ApiServer是否存在新的POD创建,根据ETCD中POD信息,依照自己的调度算法进行调度,将其调度到某一个节点 -> 存储调度信息到ETCD
      2.NODE节点:
    3. kubelet -> ApiServer -> 读取ETCD中分配给当前节点的POD信息 -> 通过Docker创建容器 -> 返回状态给ApiServer -> 存储到ETCD中
3.3.3.7.2、POD调度

影响调度的因素:

  1. POD资源限制:根据request中限制的内存CPU需求找到满足条件的NODE进行调度。
  2. 节点选择器标签
    nodeSelector:节点选择器,下图选择env_role:dev 选择的开发环境

根据设置的分组名称:组名,进行调度
1. 设置分组别名 kubectl label node node1 env_role=dev这里将node1起一个tag(名字随意)为dev标签。

查看node标记的资源标签:kubectl get nodes xxx --show-labels
3. 节点亲和性
nodeAffinity:根据节点标签约束来决定Pod调度放到哪个节点上面,有的话满足条件,不满足也可以正常使用。
1. 硬亲和性(requiredxxx):其中标注的条件必须满足(这里是目前环境中必须满足dev test),不满足就会进入等待。

  1. 软亲和性(preferref):表示尝试满足,不保证一定可以满足目标设置


weight:权重
key:环境分组Key
operator:支持常见支持符
1. In:里面包含
2. . NotIn:不包含(反亲和性)
3. Exists:存在
4. GT:大于
5. LT:小于
6. DowsNotExists:不存在

nodeSelector和nodeAffinity:POd调度到某些节点上,POd属性,调度时候实现。
3. 污点 && 污点容忍
Taint污点:不做普通的资源分配调度,是一个节点属性 实际上是一个特殊分配
场景:
1. 专用节点
2. 特定硬件节点
3. 基于污点驱逐(分配到出他以外的节点)
使用污点:
1. 查看污点 kubectl describe node xxxx | grep Taint master默认存在污点
1. NoSchedule:当前节点一定不被调度
2. NoExecute:不会调度,会驱逐当前node中其他pod到其他Node中
3. PreferNoSchdule:当前节点尽量不被调度
2. 为节点添加污点:kubectl taint node xxx key=value:污点的三个参数
3. 删除污点:kubectl taint node xxx key:污点值-
污点容忍:
配置之后虽然节点存在污点,但是仍有可能被调度到

key:污点设置的key value:污点设置的value

3.3.3.7.3、彻底删除一个POD

由于每一个POD是由Deployment进行创建管理的,因此执行kubectl delete pod xxx其实无效只是删除了一个POD而已,但是存在容灾控制,因此需要先删除相应的Deployment,之后其管理的POD会自动被删除。

  1. 查看所有的Deployment:kubectl get deployment
  2. 删除对应的Deployment:kubectl delete deployment xxx
  3. 查看对应的POD是否被删除:kubectl get pods

3.4、Controller

在集群中管理运行容器的对象

3.4.1、POD和Controller的关系

1. POD和Controller之间通过Label标签建立关系Selector


2. POD通过controller实现应用的运维,比如弹性伸缩,滚动升级等

3.4.2、Deployment控制器应用场景

Web服务、微服务
1. 部署无状态应用
2. 管理POD和ReplicaSet(副本)
3. 部署,滚动升级等功能

3.4.4、使用Depoyment控制器部署 – Yaml文件

命令行:kubectl create deployment web --image=nginx --dry-run -o=yaml生成一个yaml并不运行
打开的yaml文件:

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
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
replicas: 1
selector: #控制器绑定POD标签的选择器
matchLabels: #标签
app: web
strategy: {}
template: #POD模板
metadata:
creationTimestamp: null
labels: #POD标签
app: web #值
spec:
containers:
- image: nginx
name: nginx
resources: {}
status: {}

部署yaml文件:kubectl apply -f web.yaml

  1. 导出一个yaml kubectl create deployment web --image=镜像名称 --dry-run -o=yaml
  2. 使用命令部署 kubectl apply -f xxx.yaml
  3. 查看状态 kubectl get pods
  4. 对外暴露端口 kubectl expose deployment web --port=pod端口 --type=NodePort --target-port=外部端口 --name=发布名称 -o=yaml > web-port.yaml
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
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2022-07-18T06:56:05Z"
labels:
app: web
name: web1
namespace: default
resourceVersion: "31313"
uid: 1bc421ea-5ce8-4f54-ab4a-17e7fdfc1e4a
spec:
clusterIP: 10.102.187.245
clusterIPs:
- 10.102.187.245
externalTrafficPolicy: Cluster
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- nodePort: 32019
port: 80
protocol: TCP
targetPort: 80
selector:
app: web
sessionAffinity: None
type: NodePort
status:
loadBalancer: {}

发布:kubectl apply -f xxx.yaml

3.4.5、部署应用的升级回滚 && 弹性伸缩

先部署一个应用:设置副本和版本

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
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
replicas: 2
selector:
matchLabels:
app: web
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web
spec:
containers:
- image: nginx:1.14
name: nginx
resources: {}
status: {}
~

执行kubectl apply -f xxxx.yaml进行部署

3.4.5.1、升级

  1. 执行升级操做:kubectl set image deployment 应用名称 容器名称=容器名称:版本号
    这里对应 kubectl set image deployment web nginx=nginx:1.15

升级中:

在这个过程中,实际上副本只设置了2个,但是这里有三个,因为一个个升级,并且在下载启动设置中旧版本继续运行,最后将旧的替换掉

使用命令进行查看升级状态: kubectl rollout status deployment web

3.4.5.2、回滚

回滚版本:

  1. 查看历史版本:kubectl rollout history deployment web

  2. 回到上一个版本:kubectl rollout undo deployment web

  3. 回滚到指定版本:kubectl rollout undo --to-revision=1 deployment web

3.4.5.3、弹性伸缩

kubectl scale deployment web --replicas=10