Kubernetes 核心概念

Kubernetes 核心概念

1.1 kubernetes 集群命令行工具 kubectl
1.1.1 kubectl 概述

kubectl 是 Kubernetes 集群的命令行工具,通过 kubectl 能够对集群本身进行管理,并能够在集群上进行容器化应用的安装和部署

1.1.2 kubectl 命令格式
1
kubectl [command] [type] [name] [flags]
  • command:指定要对资源执行的操作,例如 create、get、describe、delete
  • type:指定资源类型,资源类型是大小写敏感的,开发者能够以单数 、复数 和 缩略的形式
  • name:指定资源的名称,名称也是大小写敏感的,如果省略名称,则会显示所有的资源,例如
    1
    kubectl get pods
  • flags:指定可选的参数,例如,可用 -s 或者 -server 参数指定 Kubernetes API server 的地址和端口
1.1.3 kubectl 帮助命令
1
2
3
4
5
6
# 获取 kubectl 的命令
kubectl --help

# 获取某个命令的介绍和使用
kubectl get --help
kubectl create --help
1.1.4 kubectl 基础命令
命令 介绍
create 通过文件名或标准输入创建资源
expose 将一个资源公开为一个新的 Service
run 在集群中运行一个特定的镜像
set 在对象上设置特定的功能
get 显示一个或多个资源
explain 文档参考资料
edit 使用默认的编辑器编辑一个资源
delete 通过文件名,标准输入,资源名称或标签来删除资源
1.1.5 kubectl 部署命令
命令 介绍
rollout 管理资源的发布
rolling-update 对给定的复制控制器滚动更新
scale 扩容或缩容 Pod 数量,Deployment、ReplicaSet、RC 或 Job
autoscale 创建一个自动选择扩容或缩容并设置 Pod 数量
1.1.6 kubectl 集群管理命令
命令 介绍
certificate 修改证书资源
cluster-info 显示集群信息
top 显示资源 (CPU/M)
cordon 标记节点不可调度
uncordon 标记节点可被调度
drain 驱逐节点上的应用,准备下线维护
taint 修改节点 taint 标记
1.1.7 kubectl 故障和调试命令
命令 介绍
describe 显示特定资源或资源组的详细信息
logs 在一个 Pod 中打印一个容器日志,如果 Pod 只有一个容器,容器名称是可选的
attach 附加到一个运行的容器
exec 执行命令到容器
port-forward 转发一个或多个端口
proxy 运行一个 proxy 到 Kubernetes API Server
cp 拷贝文件或目录到容器中
auth 检查授权
1.1.8 kubectl 其它命令
命令 介绍
apply 通过文件名或标准输入对资源应用配置
patch 使用补丁修改、更新资源的字段
replace 通过文件名或标准输入替换一个资源
convert 不同的 API 版本之间转换配置文件
label 更新资源上的标签
annotate 更新资源上的注释
completion 用于实现 kubectl 工具自动补全
api-versions 打印受支持的 API 版本
config 修改 kubeconfig 文件(用于访问 API,比如配置认证信息)
help 所有命令帮助
plugin 运行一个命令行插件
version 打印客户端和服务版本信息
1.2 Kubernetes 集群 YAML 文件详解
1.2.1 YAML 概述
  • YAML 文件 : 就是资源清单文件,用于资源编排。
  • YAML : 仍是一种标记语言。为了强调这种语言以数据做为中心,而不是以标记语言为重点。
  • YAML : 是一个可读性高,用来表达数据序列的格式。
1.2.2 YAML 基本语法
  • 使用空格做为缩进
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • 低版本缩进时不允许使用 Tab 键,只允许使用空格
  • 使用#标识注释,从这个字符一直到行尾,都会被解释器忽略
  • 使用 — 表示新的 yaml 文件开始
1.2.3 YAML 数据结构

对象:键值对的集合,又称为映射 (mapping) / 哈希(hashes) / 字典(dictionary)

1
2
3
4
5
6
# 对象类型:对象的一组键值对,使用冒号结构表示
name: hqd8080
age: 18

# yaml 也允许另一种写法,将所有键值对写成一个行内对象
hash: {name: hqd8080, age: 18}

数组:

1
2
3
4
5
6
7
# 数组类型:一组连词线开头的行,构成一个数组
People
- hqd8080
- Jack

# 数组也可以采用行内表示法
People: [hqd8080, Jack]
1.2.4 YAML 组成部分

主要分为了两部分,一个是控制器的定义 和 被控制的对象。 在一个 YAML 文件的控制器定义中,有很多属性名称

属性名称 介绍
apiVersion API 版本
kind 资源类型
metadata 资源元数据
spec 资源规格
replicas 副本数量
selector 标签选择器
template Pod 模板
metadat Pod 元数据
spec Pod 规格
containers 容器配置
1.2.5 YAML 快速编写

一般来说,我们很少自己手写 YAML 文件,因为这里面涉及到了很多内容,我们一般都会借助工具来创建

1、使用 kubectl create 命令
这种方式一般用于资源没有部署的时候,我们可以直接创建一个 YAML 配置文件

1
2
# 尝试运行,并不会真正的创建镜像
kubectl create deployment web --image=nginx -o yaml --dry-run

或者我们可以输出到一个文件中

1
kubectl create deployment web --image=nginx -o yaml --dry-run > nginx.yaml

然后我们就在文件中直接修改即可

2、使用 kubectl get 命令导出 yaml 文件

可以首先查看一个目前已经部署的镜像

1
kubectl get deploy

然后我们导出 nginx 的配置

1
kubectl get deploy nginx -o=yaml --export > nginx.yaml

然后会生成一个 nginx.yaml 的配置文件

1.3 Pod
1.3.1 Pod 概述
1、Pod 基本概念
  • 最小部署的单元、Pod 里面是由一个或多个容器组成【一组容器的集合】
  • 一个 pod 中的容器是共享网络命名空间
  • Pod 是短暂的
  • 每个 Pod 包含一个或多个紧密相关的用户业务容器
2、Pod 存在的意义
  • 创建容器使用 docker,一个 docker 对应一个容器,一个容器运行一个应用进程
  • Pod 是多进程设计,运用多个应用程序,也就是一个 Pod 里面有多个容器,而一个容器里面运行一个应用程序
  • Pod 的存在是为了亲密性应用
  • 两个应用之间进行交互 、网络之间的调用【通过 127.0.0.1 或 socket】、两个应用之间需要频繁调用
3、k8s 业务类型

Pod 是 K8S 集群中所有业务类型的基础,可以把 Pod 看作运行在 K8S 集群上的小机器人,不同类型的业务就需要不同类型的小机器人去执行。目前 K8S 的业务主要可以分为以下几种

  • 长期伺服型:long-running
  • 批处理型:batch
  • 节点后台支撑型:node-daemon
  • 有状态应用型:stateful application

上述的几种类型,分别对应的小机器人控制器为:Deployment、Job、DaemonSet 和 StatefulSet (后面将介绍控制器)

1.3.2 Pod 实现机制

Pod 主要有以下两大机制:共享网络 和 共享存储

1、共享网络【容器通过 namespace 和 group 进行隔离】

Pod 中容器通信 过程:

  • 同一个 namespace 下
  • 在 Pod 中创建一个根容器: pause 容器
  • 在 Pod 中创建业务容器 【nginx,redis 等】【创建时会添加到 info 容器 中】
  • 在 info 容器 中会独立出 ip 地址,mac 地址,port 等信息,然后实现网络的共享
2、共享存储【Pod 持久化数据,专门存储到某个地方中,使用 Volumn 数据卷进行共享存储】
1.3.3 Pod 镜像拉取策略

我们以具体实例来说,拉取策略就是 imagePullPolicy、拉取策略主要分为了以下几种:

  • IfNotPresent:默认值,镜像在宿主机上不存在才拉取
  • Always:每次创建 Pod 都会重新拉取一次镜像
  • Never:Pod 永远不会主动拉取这个镜像
1.3.4 Pod 资源限制
也就是我们 Pod 在进行调度的时候,可以对调度的资源进行限制,例如我们限制 Pod 调度是使用的资源是 2C4G,那么在调度对应的 node 节点时,只会占用对应的资源,对于不满足资源的节点,将不会进行调度

这里分了两个部分:

  • request:表示调度所需的资源
  • limits:表示最大所占用的资源
1.3.5 Pod 重启机制

因为 Pod 中包含了很多个容器,假设某个容器出现问题了,那么就会触发 Pod 重启机制

重启策略主要分为以下三种:

  • Always:当容器终止退出后,总是重启容器,默认策略 【nginx 等,需要不断提供服务】
  • OnFailure:当容器异常退出(退出状态码非 0)时,才重启容器
  • Never:当容器终止退出,从不重启容器 【批量任务】
1.3.6 Pod 健康检查

1、通过容器检查:

1
kubectl get pod

2、通过应用检查:

但是有的时候,程序可能出现了 Java 堆内存溢出,程序还在运行,但是不能对外提供服务了,这个时候就不能通过容器检查来判断服务是否可用了。需要通过应用检查

1
2
3
4
5
# 存活检查,如果检查失败,将杀死容器,根据 Pod 的 restartPolicy【重启策略】来操作
livenessProbe

# 就绪检查,如果检查失败,Kubernetes 会把 Pod 从 Service endpoints 中剔除
readinessProbe

Probe 支持以下三种检查方式

  • http Get:发送 HTTP 请求,返回 200 - 400 范围状态码为成功
  • exec:执行 Shell 命令返回状态码是 0 为成功
  • tcpSocket:发起 TCP Socket 建立成功
1.3.7 Pod 调度策略
  • 首先创建一个 pod,然后创建一个 API Server 和 Etcd【把创建出来的信息存储在 etcd 中】
  • 然后创建 Scheduler,监控 API Server 是否有新的 Pod,如果有的话,会通过调度算法,把 pod 调度某个 node 上
  • 在 node 节点,会通过 kubelet – apiserver 读取 etcd 拿到分配在当前 node 节点上的 pod,然后通过 docker 创建容器
1.4 Controller
1.4.1 Controller 内容简介
  • 什么是 Controler
  • Pod 和 Controller 的关系
  • Deployment 控制器应用场景
  • yaml 文件字段说明
  • Deployment 控制器部署应用
  • 升级回滚
  • 弹性收缩
1.4.2 Controller 概述

Controller 是集群上管理和运行容器的对象

  • Controller 是实际存在的
  • Pod 是虚拟机的
1.4.3 Pod 和 Controller 的关系

Pod 是通过 Controller 实现应用的运维,比如弹性收缩,滚动升级

Pod 和 Controller 之间是通过 label 标签建立关系,同时 Controller 又被称为控制器工作负载

  • Controller【控制器】【工作负载】selector: app:nginx
  • Pod【容器】labels: app:nginx
1.4.4 Deployment 控制器应用

Deployment 表示用户对 K8S 集群的一次更新操作

  • Deployment 控制器可以部署无状态应用
  • 管理 Pod 和 ReplicaSet
  • 部署,滚动升级等功能
  • 应用场景:web 服务,微服务
1.4.5 Deployment 部署应用

之前,使用 deployment 部署应用,代码如下:【缺点:代码不好复用】

1
kubectrl create deployment web --image=nginx

现在,使用 YAML 文件进行配置:【快速编写 YAML 文件】

1
kubectl create deployment web --image=nginx -o yaml --dry-run > nginx.yaml

nginx.yaml 文件内容如下:【selectorlabel 就是我们 Pod 和 Controller 之间建立关系的桥梁】

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

现在,使用nginx.yaml文件创建镜像:

1
kubectl apply -f nginx.yaml

然后,对外暴露端口:

1
2
3
4
5
6
7
kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=web1

# 参数说明
# --port:就是我们内部的端口号
# --target-port:就是暴露外面访问的端口号
# --name:名称
# --type:类型

同理,导出配置文件:

1
kubectl expose deployment web --port=80 --type=NodePort --target-port=80 --name=web1 -o yaml > web1.yaml

查看端口:

1
2
3
4
5
6
7
8
9
kubectl get pods,svc

# 输出结果
NAME READY STATUS RESTARTS AGE
pod/web-5dcb957ccc-d89v9 1/1 Running 0 8m35s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d5h
service/web1 NodePort 10.111.61.143 <none> 80:30344/TCP 6s

然后我们访问对应的 url,即可看到 nginx 了 http://192.168.60.151:30344/

1.4.6 升级回滚和弹性收缩
  • 升级: 假设从版本为 1.14 升级到 1.15 ,这就叫应用的升级【升级可以保证服务不中断】
  • 回滚:从版本 1.15 变成 1.14,这就叫应用的回滚
  • 弹性伸缩:我们根据不同的业务场景,来改变 Pod 的数量对外提供服务,这就是弹性伸缩
1、创建一个 1.14 版本的 pod
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:
# 修改 nginx 版本 1.14
- image: nginx:1.14
name: nginx
resources: {}
status: {}
1
kubectl apply -f nginx.yaml
2、应用升级
1
kubectl set image deployment web nginx=nginx:1.15

升级过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@master ~]# kubectl set image deployment web nginx=nginx:1.15
deployment.apps/web image updated

# 首先是开始的 nginx 1.14 版本的 Pod 在运行,然后 1.15 版本的在创建
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-66bf4959f5-qhzsd 1/1 Running 0 52s
web-bbcf684cb-bbmqv 0/1 ContainerCreating 0 3s

# 然后在 1.15 版本创建完成后,就会暂停 1.14 版本
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-66bf4959f5-qhzsd 1/1 Terminating 0 67s
web-bbcf684cb-bbmqv 1/1 Running 0 18s

# 最后把 1.14 版本的 Pod 移除,完成我们的升级
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-bbcf684cb-bbmqv 1/1 Running 0 33s

我们在下载 1.15 版本,容器就处于 ContainerCreating 状态,然后下载完成后,就用 1.15 版本去替换 1.14 版本了,这么做的好处就是:升级可以保证服务不中断

3、查看升级状态
1
kubectl rollout status deployment web
4、查看历史版本
1
kubectl rollout history deployment web
5、应用回滚
1
2
3
4
5
# 回滚到上一版本
kubectl rollout undo deployment web

# 回滚到指定版本
kubectl rollout undo deployment web --to-revision=2
6、弹性伸缩
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 通过命令创建多个副本
kubectl scale deployment web --replicas=10

# 输出结果,等一会就会全部 Running
[root@master ~]# kubectl scale deployment web --replicas=10 deployment.apps/web scaled
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-bbcf684cb-2f2zl 0/1 ContainerCreating 0 4s
web-bbcf684cb-72pzr 0/1 ContainerCreating 0 4s
web-bbcf684cb-bbmqv 1/1 Running 0 3m9s
web-bbcf684cb-fgpgh 0/1 ContainerCreating 0 4s
web-bbcf684cb-fpk8d 0/1 ContainerCreating 0 4s
web-bbcf684cb-hqp4z 0/1 ContainerCreating 0 4s
web-bbcf684cb-htq2d 0/1 ContainerCreating 0 4s
web-bbcf684cb-lnkwx 0/1 ContainerCreating 0 4s
web-bbcf684cb-vmwb9 0/1 ContainerCreating 0 4s
web-bbcf684cb-vnk5w 0/1 ContainerCreating 0 4s