K8S资源管理
简介:在k8s中,所有的内容都抽象为资源。用户需要通过操作资源来管理k8s
- k8s就是集群系统,用户可以在集群中部署各种服务,即在k8s中运行一个个容器,并将指定的程序跑在容器中
- k8s最小管理单元是pod而不是docker.k8s也不直接管理pod,而是通过pod控制器管理pod
- Pod可以提供服务之后,就考虑如何访问Pod中的服务。Service承担这个功能
- Pod数据如果需要存储话, k8s提供了存储系统方便数据持久化
所以说,k8s的核心就是学习Pod, Pod控制器, Service, 存储等资源进行操作
YAML语言
yaml是一个类似XML, JSON的标记行语言。强调以数据为中心,因此语法结构简单,和Json一样是数据格式语言
YAML重点语法与特点:
- 大小写敏感
- 使用缩进表示层级关系
- 缩进的空格数不重要,但是相同层级数量相同。所有变量的 ‘:’ 后面要加空格
- #表示注释
- (低版本不兼容tab, 如果你的tab 报错那就换成空格吧)
# eg. 以JSON为例
{
this is a object:{
name: 老王,
age: 114514,
birthday: "2022-04-01",
favorate:['sing','jump','rap','basketball'],
knows: ['python','k8s','django','deeplearning'],
have_girlfirend: False,
like_people:null,
best_friend: "xiongbinyan"
}
this is object:
name: 老王
age: 114514
birthday: 2022-04-01 # 必须使用ISO 8601格式,即year-mm-dd
# 下面是数组的两种写法
favorate: favorate:['sing','jump','rap','basketball']
knows:
- python
k8s
django
deeplearning
have_girefriend: False
like_people: ~
best_friend: xiongbinyan # 这里可以加单引号,可以夹单双引号,也可以不加
YAML支持的数据类型:
- 纯量:布尔类型, 整形, 浮点型, null类型,日期类型,时间类型,字符换类型
- 对象:键值对的集合
- 数组:有序排列的多个值
TIPS: 如果多个yaml配置放在一个文件中, 需要加— 代表文件分段(数量就是3个,不多不少)
资源管理方式
-
命令式对象管理:直接使用命令操作kubernetes的资源
# 运行一个pod, 指定pod的iamge与暴漏端口 kubectl run nginx-pod --image-=nginx --port=80
-
命令式对象配置:通过命令配置和配置文件操作k8s资源
# 创建与更新(patch), 和上面基本相同,不过参数由配置文件提供 kubectl create/patch -f nginx-pod.yaml
-
声明式对象配置: 通过apply命令和配置文件去操作kubernetes资源
# 完全按照配置文件进行配置,只能完成创建与更新资源 kubectl apply -f nginx-pod.yaml
类型 操作 适用于 优点 缺点 命令式对象管理 对象 测试 简单 简单操作无法审计与追踪 命令式对象配置 文件 开发 可以审计追踪 项目大时配置文件多比较麻烦 声明式对象配置 目录 开发 支持目录操作 难以进行调试 -
命令式对象管理:
kubectl命令格式:
kubectl [command] [type] [name] [flags]
command: 指定对资源执行的操作, 如create, get delete
type: 指定资源类型: pod, deployment, service
name: 指定资源的名称,名称大小写敏感
flags: 指定额外的可选参数.
# 查看所有用户级pod kubectl get pod # 查看具体的pod,以及详细信息 kubectl get pod nginx-f89759699-vwjnl -owide # 获取所有pod, 包括kube_system 系统级。这也式我们上面调bug回溯时候用过的 kubectl get pod -A -owide # 将配置以文件形态输出,可选json或yaml kubectl get pod -o json
下面就是常用的命令罗列了:
command 系列: 所有命令查看 kubectl --help
-
基本命令: create 创建,edit 编辑, get 获取, patch 更新, delete 删除, explain 解释,version 查看版本
-
运行于调试: run 运行,在集群中指定一个运行的镜像
expose 暴露接口,方便外界访问
describe 描述资源的状态于内部信息,用来debug, 很常用
logs 日志, 输出容器在pod中的日志
exec 执行,执行容器中的一个命令
cp 复制,在pod内外复制文件
scale/autoscale 手动调整/ 自动调整Pod数量
-
高级命令: apply 通过文件对资源进行配置
label 更新资源上的标签
type 系列: 所有命令查看: kubectl api-resources (下面括号中的东西代表缩写的样子)
-
集群级别资源: nodes(no) 节点,集群组成部分
namespace (ns) 隔离pod
-
pod 资源 pods (po) 装载容器
-
服务发现资源 service (svc) 统一pod对外接口
Ingress (ing) 统一pod对外接口
-
存储资源, 配置资源,pod资源控制器,太大了放不下,后面有需要会写
-
-
命名式对象配置:(简单了解命名格式)
下面是一个简单的pod.yaml
# 上面这一段式配置命名空间的。新建一个命名空间名字叫做nginxx apiVersion: v1 kind: Namespace metadata: name: nginxx --- # 下面这一段是新建pods的,指定了姓名和namespace apiVersion: v1 kind: Pod metadata: name: nginx_hello namespace: nginxx spec: containers: - name: nginx-containers image: nginx
-
声明式对象配置:
和2差不多。但是只能用apply 和 create, 要用delete的时候和2相同
-
K8S 资源简介:
NameSpace
NameSpace是kubernetes系统中一个非常重要的资源。主要作用是实现多套环境的资源隔离或多租户的资源隔离,就类似于Linux用户认证的组策略一样。
默认情况下我们的pod都会放到deafult这个命名空间下,所有的pod是互联的。但实际情况下有些时候我们不想让pod进行互联,就可以放到Namespace种形成逻辑上的组
还可以通过k8s的授权机制,将不同的ns交给不同用户管理,这样就实现了多租户资源隔离。还可以已通过k8s的资源配额限制限定不同租户不能占用的资源,实现用户资源管理。
k8s集群在启动的时候会默认常见一些namespace:
kubectl get ns
# Status包括两个状态:Active正在使用, Terminating: 正在删除
NAME STATUS AGE
# 默认命名空间,放置所有未指定ns的资源对象
default Active 21h
# 集群节点之间的心跳维护
kube-node-lease Active 21h
# 此命名空间下的资源可以被所有人,包括未命名的账户访问
kube-public Active 21h
# 所有由k8s创建的资源都位于此命名空间,放置一些集群组件等
kube-system Active 21h
基本命令:
kubectl get/delete ns
kubectl get/delete ns 具体名称
kubectl describe ns 名称
Pod
Pod是K8s集群进行管理的最小单元,程序必须部署在容器中,而容器必须部署在Pod中。Pod可以认为是容器的封装,一个Pod可以存在一个或者多个容器。创建的每个POD都会存在一个Pause的容器,即根容器。根容器的意义如下:
- 在一组容器作为一个单位的情况下,我们难以简单地对整组容器的状态进行判断。如果其中一个容器死亡,此时该去定义整组容器都死亡呢?还是定义N/M的死亡率呢?通过引入与业务无关并且不容易死亡的Pause容器作为Pod的根容器,以它的状态代表整组容器的状态,可以简单的解决整个问题。
- Pod里的多个业务容器共享Pause容器IP,共享Pause容器挂接的Volume,这样既简化了密切关联的业务容器之间的通信问题,也很好地解决了它们之间的文件共享问题。换句话说为了保证同一Pod不同docker数据卷挂载,数据持久化与共享,产生了根容器。
上面我们提到了系统层的命名空间,现在我们就看看系统曾的命名空间中都有什么Pod吧:
kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
# 两个dns组件
coredns-7ff77c879f-fz6jj 1/1 Running 0 21h
coredns-7ff77c879f-wfcsb 1/1 Running 0 21h
# 这四个是master节点的核心组件,详见最开头那张图
etcd-vm-0-13-ubuntu 1/1 Running 0 21h
kube-apiserver-vm-0-13-ubuntu 1/1 Running 0 21h
kube-controller-manager-vm-0-13-ubuntu 1/1 Running 0 21h
kube-scheduler-vm-0-13-ubuntu 1/1 Running 0 21h
# flannel网络组件,负责子网下的docker网络访问。我部署了两个节点所以由两个
kube-flannel-ds-4h24x 1/1 Running 0 21h
kube-flannel-ds-b65bm 1/1 Running 0 21h
# 访问代理,就是对pods中的docker代理的
kube-proxy-2nb9g 1/1 Running 0 21h
kube-proxy-kw79r 1/1 Running 0 21h
一个简单的pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: anginxpod
namespace: hellok8s
spec:
containers:
- image: nginx
# 镜像拉取策略:镜像拉取策略有三种 Always(默认,只从网上拉)、Never (只用本地有的) 、IfNotPresent(本地有就用本地的,没有上网拉)
imagePullPolicy: IfNotPresent
# 这个name是指容器的名称
name: nginx-container
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
Label
看到这个名字就应该知道这玩应是用来干啥的了。作用是在资源上添加表示,用来对资源进行区分与选择。
- 一个Label会以key/value键值对的形式添加到各种对象上,如Node, Pod, Service
- 一个资源对象可以定义任意数量的Label. 一个Label也可以添加到任意数量的资源上
- Label通常在对象定义的时候确定,当然也可以在对象创建之后动态的添加或者删除。
当然定义完标签之后为了方便我们分类我们还要搞一个label selector. 我们可以选择:
-
基于等式的Label selector, =
eg. name = slave 选择所有Label中有name属性且等于 slave的对象
-
基于集合的Label selector, in
name in (master, node1) 选择所有Label中有name且等于master或slave的对象
上面的两种查询方式支持复合使用
配置方式,直接在meta中给出相应的键值对即可:
apiVersion: v1
kind: Pod
metadata:
name: anginxpod
namespace: hellok8s
label:
version: "2.9"
env: "test"
spec: "This is a testing round, Hope there'll be No bug"
# ......下面一堆自己随意补齐就好啦
当然,标签也可以用命令行添加:
# 获取标签
kubectl get pod --show-labels
# 打标签. 这里注意标签要求,额就是'_','-','.',字母可以,其他军不行(报错信息)
kubectl label pod XXX version=1.1 spec="first-k8s-with-nginx"
# show的结果如下
NAME READY STATUS RESTARTS AGE LABELS
nginx-f89759699-vwjnl 1/1 Running 0 23h app=nginx,pod-template-hash=f89759699,spec=first-k8s-with-ngi
# 更新
kubectl label pod XXX ~~~~~~~~~ --overwrite
# 删除
kubectl label pod XXX spec-
Deployment
在k8s中Pod是最小的控制的单元, 但是k8s很少直接的控制pod, 一般用控制器,Deployment是控制器中比较常见的一种,确保pod符合预期状态。当出现故障会尝试重建pod
基本操作:
kubectl get deploy
kubectl get deploy -owide
#自定义pod的数量
kubectl run sonename --image=XXX --port=XXX --replicas=3
一个简单的配置demp:
apiVersion: v1
kind: Namespace
metadata:
name: hellok8s
---
# 这里我也不知道为啥直接v1会报错,后面再看看吧
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-try
namespace: hellok8s
spec:
# 创建的pods数量
replicas: 2
# 需要创建选择器,标签采用下面的nginx, 必须要有
selector:
matchLabels:
name: nginxxx
# 创建pod模板
template:
metadata:
labels:
version: "1.1"
spec: this-is-a-deploy-try
name: nginxxx
name: nginx_pod
spec:
containers:
- image: nginx
name: nginx
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
我们查看的时候就有两个pod了:
kubectl get pod -n hellok8s
NAME READY STATUS RESTARTS AGE
nginx-try-7c7b7f8c6d-2t2tx 1/1 Running 0 71s
nginx-try-7c7b7f8c6d-6rljn 1/1 Running 0 71s
Service
我们用depoly虽然创建出了一组pod, 但是由于**Pod IP会不断变化(Pod不断打开又关闭)且没有外部访问的端口,**给我们访问带来了困难。 kubernetes利用Service解决了这个问题。
Service可任意看作是一组同类Pod对外访问的接口。借助Service我们可以更方便的实现服务发现与负载均衡。
简单的Service操作:
# 参数介绍:name svc的名称 需要用deploy去找需要暴漏的pod type ClusterIP是指只供集群内部访问的集群IP, 使用NodePort可以转换成公网可以访问的端口。port和target_pod我也没分清究竟哪个是干啥的。。
kubectl expose deploy nginx-try --port=80 --target-port=80 --name=hello-service --type=NodePort -n hellok8s
kubectl get svc -n hellok8s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-service NodePort 10.105.90.124 <none> 80:32606/TCP 3s
一个Service的简单的yaml
apiVersion: v1
kind: Service
metadata:
name: hello-nginx-service
namespace: hellok8s
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
# 不知道为什么上面(deploy)就一定要用matchLabels, 下面用就会报错(需要的是String你给了一个map)
# matchLabels:
name: nginxxx
type: NodePort
POD
上面我们了解了基本的资源对象知识。但是只是一个比较简略的介绍。接下来我们将围绕Pod进行具体的展开。
Pod结构:
Pod的结构图我其实前面放过,不过再放一边吧。每个Pod由多张镜像组成, 每个Pod中包含:我们自定义的容器, Pod根容器。Pod跟容器的作用我前面说过一次,在这里做简略补充
Pause容器的作用:
-
可以以它为依据,评估整个Pod的健康状态
-
可以在根容器上设置ip地址,其它容器都此ip(Pod ip),以实现Pod内部的网路通信, 相当于是网络二级虚拟化的过程
我们可以用命令获取一个pod的资源清单:(直接摘抄的这位老哥的 https://gitee.com/yooome/golang/blob/main/k8s%E8%AF%A6%E7%BB%86%E6%95%99%E7%A8%8B/Kubernetes%E8%AF%A6%E7%BB%86%E6%95%99%E7%A8%8B.md#44-deployment)
# 用一个系统自创建的示例来看看pod自定义能包含那些内容
kubectl get pod -o yaml
# 一份标准的配置文件清单模板:
# 这玩意直接看确实挺头痛的
apiVersion: v1 #必选,版本号,例如v1
kind: Pod #必选,资源类型,例如 Pod
metadata: #必选,元数据
name: string #必选,Pod名称
namespace: string #Pod所属的命名空间,默认为"default"
labels: #自定义标签列表
- name: string
spec: #必选,Pod中容器的详细定义
containers: #必选,Pod中容器列表
- name: string #必选,容器名称
image: string #必选,容器的镜像名称
imagePullPolicy: [ Always|Never|IfNotPresent ] #获取镜像的策略
command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令
args: [string] #容器的启动命令参数列表
workingDir: string #容器的工作目录
volumeMounts: #挂载到容器内部的存储卷配置
- name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符
readOnly: boolean #是否为只读模式
ports: #需要暴露的端口库号列表
- name: string #端口的名称
containerPort: int #容器需要监听的端口号
hostPort: int #容器所在主机需要监听的端口号,默认与Container相同
protocol: string #端口协议,支持TCP和UDP,默认TCP
env: #容器运行前需设置的环境变量列表
- name: string #环境变量名称
value: string #环境变量的值
resources: #资源限制和请求的设置
limits: #资源限制的设置
cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
requests: #资源请求的设置
cpu: string #Cpu请求,容器启动的初始可用数量
memory: string #内存请求,容器启动的初始可用数量
lifecycle: #生命周期钩子
postStart: #容器启动后立即执行此钩子,如果执行失败,会根据重启策略进行重启
preStop: #容器终止前执行此钩子,无论结果如何,容器都会终止
livenessProbe: #对Pod内各容器健康检查的设置,当探测无响应几次后将自动重启该容器
exec: #对Pod容器内检查方式设置为exec方式
command: [string] #exec方式需要制定的命令或脚本
httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
path: string
port: number
host: string
scheme: string
HttpHeaders:
- name: string
value: string
tcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式
port: number
initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒
timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
successThreshold: 0
failureThreshold: 0
securityContext:
privileged: false
restartPolicy: [Always | Never | OnFailure] #Pod的重启策略
nodeName: <string> #设置NodeName表示将该Pod调度到指定到名称的node节点上
nodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上
imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定
- name: string
hostNetwork: false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
volumes: #在该pod上定义共享存储卷列表
- name: string #共享存储卷名称 (volumes类型有很多种)
emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
path: string #Pod所在宿主机的目录,将被用于同期中mount的目录
secret: #类型为secret的存储卷,挂载集群与定义的secret对象到容器内部
scretname: string
items:
- key: string
path: string
configMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
name: string
items:
- key: string
path: string
当然,面对上面这种一大堆的头秃文字,是个人都不会直接看的。这里就可一用到另一个命令救场
# explain可以列出每种资源的可配置项,更可以具体看某个可配置项的具体信息
kubectl explain pods
# 查找具体内容请这么使用
kubectl explain pods.spec
在K8s中所有资源的一级属性都是一样的,主要包含五个主类:
- apiVersion 版本, 由kubernetes内部定义,版本号必须可以用kubectl api-versions查询到(话句话说只要用这个命令查了填就行)
- kind类型: 由k8s内部定义, 版本号必须可以由kubectl api-resoueces 查询到。
- metadata: 元数据,组要是资源的标识和说明,包括name, label等标签性质的对象
- spec: 重要的具体参数配置,里面是对各种资源配置的详细描述
- status:状态信息: 里面的内容无需定义,由k8s自己生成