2022-12-28-k8s中常见的资源对象的使用
K8S设计理念
分层架构,从高到低依次为;
1.云原生生态系统:云原生生态系统是在接口层之上的kubernetes的集群管理调度生态系统,有两个范畴
1.1 kubernetes内部:CRI,CNI,CSI,镜像仓库;
CRI:container runtime interface 容器运行时接口
CNI:container network interface 容器网络接口
CSI:container storage interface 容器存储接口
1.2 kubernetes外部:监控,日志,CI/CD,配置管理等;
2.接口层:客户端库和使用工具:kubectl命令行工具和SDK等客户访问接口;
3.管理层:自动化和策略管理:自动化体现在:如pod伸缩,动态存储卷创建和回收。策略管理体现在:如资源限制,RBAC授权,NetworkPolicy等;主要解决项目之间的pod隔离,网络安全,自动伸缩等功能;
4.应用层:部署和路由:应用层实现服务部署(无状态应用如nginx使用deployment,有状态应用如mysql主从使用statefulset)和路由(通过service实现之间调用);
5.核心层:kubernetes API和执行环境:核心层包括kubernetes的AIP,service,控制器,namespace,node等,是运行pod的基础环境;
6.底层硬件和网络
AIP设计原则:
1.所有API都是声明式的;
2.API对象是彼此互不而且可以互相组合的;
3.高层API以操作意图为设计基础;
4.低层API根据高层API的控制需要设计;
5.尽量避免简单封装,不要有在外部API无法显示知道的内部隐藏机制;
6.API操作复杂度与对象数量成正比;
7.API对象状态不能依赖于网络状态;
8.尽量避免让操作机制依赖于全局状态,因为在分布式系统中要保证全局状态是很难的;
K8S,API简介
# kubectl api-resources #查询所有API接口;
内置API:部署好kubernetes后自带的API接口;
自定义资源对象:CRD(Custom Resource Definition),部署好kubernetes后通过安装其他组件等方式扩展出来的API;

Kubernetes重要概念
资源对象:Kubernetes的声明式API,和资源对象进行交互;
yaml文件:为了方便后期管理,使用yaml文件调用API实现对资源对象的管理;
yaml文件必要字段:
1.apiVersion:创建该对象所要使用的api版本;
2.kind:想要创建的对象类型;
3.metadata:定义识别对象的唯一性数据,包括一个name名称,可选的namesapce;
4.spec:定义资源对象的详细规范信息(统一的lable标签,容器名称,镜像,映射端口等);
5.status:pod创建完成后K8S自动生成status状态;
pod
1.pod是K8S中的最小调度单元;
2.一个pod中可以运行一个容器也可以运行多个容器;
3.运行多个容器的话,这些容器是一起被调度的;
4.pod的生命周期是短暂的,不会自愈,是用完就销毁的实体;
5.一般我们是通过controller来创建和管理pod的;
job和cronjob:单次任务和周期任务;注意,这种pod在构建yaml文件时,需要考虑到是否允许重构的问题;
job通常用来执行数据或者环境的初始化,使用方法同样是通过创建yaml来实现,可以理解为创建一个kind为job的pod,来实现初始化的操作;
cronjob用来执行周期性任务,例如备份,使用方法同上。每次执行创建一个新的pod;
RC/RS副本控制器:
Replication Controller:早期使用;
ReplicaSet:
Deployment:现在使用的控制器,拥有回滚,滚动升级等高级功能;
3种副本控制器创建pod的名称示例;
ReplicationController:
ng-rc-tbln8
ng-rc-5swk5
ReplicaSet:
frontend-bbtcc
frontend-qj5mw
kubectl set image replicaset/frontend ng-rs-80=nginx:1.20.0
Deployment:
nginx-deployment-ccbf969f7-d9w4t
nginx-deployment-ccbf969f7-f7zpr
滚动更新机制:优先新建,然后替代原有容器,直到容器个数符合控制器要求;
Service简介
由于pod重建后IP会发生变化,因此pod之间使用固定IP访问的方式将不再可行,而service则解耦了服务和应用,service的实现方式就是,通过label动态标签匹配后端endpoint;
kube-proxy监听着,k8s-apiservice,一旦service资源发生变化(调K8S-api修改service信息),kube-proxy就会生成对应的负载调度调整,这样就保证了service的最新状态;
kube-proxy有三种调度模型:
1.userspace
2.iptables
3.ipvs:1.11版本之后,如果没有主动开启ipvs则会降级为iptables;

K8S访问的通信流程:

1.客户发布请求到负载均衡服务,如要访问192.168.1.10(负载均衡服务地址)30004端口;
2.负载均衡收到请求后将请求转发给后端真实服务地址(K8S环境中为pod地址)
先创建一个测试用pod
# kubectl apply -f ng-deploy-80.yaml
apiVersion:apps/v1
kind:Deployment
metadata:
name:nginx-deployment
spec:
replicas:1
selector:
matchLabels:#rs or deployment;
app:ng-deploy-80
tamplate:
metadata:
labels:
app:ng-deploy-80
spec:
containers:
-name:ng-deploy-80
image:nginx:1.20.0
ports:
-containerPort:80

Service有四种类型
1.ClusterIP:只在K8S内部使用,service通过此IP对各个pod进行调用;
apiVersion:v1
kind:Service #声明该资源对象的类型;
metadata:
name:ng-deploy-80 #定义该pod的名称;
spec:
ports:
-name:http #声明这个service负责的服务名称;
port:80 #声明这个service使用的端口;
targetPort:80 #声明集群内各个pod使用80端口与service通信;
protocol:TCP #使用协议类型;
#type: ClusterIP #默认类型就是ClusterIP;
#ClusterIP: 192.168.xx.xx #声明使用一个固定的ClusterIP来进行通信,这样做的目的是,当集群中有某个服务要指定调用个别功能时才会用到;
selector:
app:ng-deploy-80 #在标签选择器中定义该pod与哪个标签的pod绑定;


2.ExternalName:
3.LoadBalancer:
4.NodePort:会在每个node上监听一个相同的端口,用户客户端的访问,会把请求转发至对应的service,然后由service转发给pod,用于将K8S中的服务暴露给K8S环境以外的客户端访问;
注意和clusterIP的区别;
apiVersion:v1
kind:Service #声明该资源对象的类型;
metadata:
name:ng-deploy-80 #定义该pod的名称,如果有多个相同名称的pod则后者顶掉前者;
spec:
ports:
-name:http
port:81 #可以理解为service的端口,因为service也需要端口和IP和pod通信;
targetPort:80 #真正提供服务的pod服务端口
nodePort:30080 #用户访问的端口,提供服务的端口映射
protocol:TCP #使用协议类型;
type:NodePort #声明此service是NodePort类型;
selector:
app:ng-deploy-80 #在标签选择器中定义该pod与哪个标签的pod绑定;

Volume存储卷简介
Volume将容器中的指定数据和容器解耦,并将数据存储到指定位置,不同的存储卷功能不一样,如果是基于网络存储的存储卷可以实现数据的共享和持久化;
静态的存储卷需要在使用前手动创建pv和pvc,然后绑定到pod使用;
常用的卷有以下几种:
secret:是一种包含少量敏感信息例如密码,令牌和密钥的对象;
configmap:配置文件;
emptyDir:本地临时卷;
当pod被分配个节点时,首先创建emptyDir卷,并且只要该pod在该节点上运行,该卷就会存在。正如该卷的名字所述,改卷最初为空,pod中的容器可以读取和写入该卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径,但处于任何原因造成该pod从该节点中被删除时,emptyDir中的数据将被永久删除;
测试emptyDir;
apiVersion:apps/v1
kind:Deployment
metadata:
name:nginx-deployment
spec:
replicas:1
selector:
matchLabels:#rs or deployment
app:ng-deploy-80
template:
metadata:
labels:
app:ng-deploy-80
spec:
containers:
-name:ng-deploy-80
image:nginx
ports:
-containerPort:80
volumeMounts:
-mountPath:/cache #容器当中挂载的位置;
name:cache-volume #容器当中挂载的名称;
volumes:
-name:cache-volume #声明卷的名字;
emptyDir: {} #所使用的卷类型;

登录容器,写入测试文件

到启动pod的node节点上查找对应文件,可以看到文件已经生成;

hostPath:本地存储卷,数据存储在宿主机本地,不会丢失;
测试hostPath
apiVersion:apps/v1
kind:Deployment
metadata:
name:nginx-deployment
spec:
replicas:1
selector:
matchLabels:
app:ng-deploy-80
template:
metadata:
labels:
app:ng-deploy-80
spec:
containers:
-name:ng-deploy-80
image:nginx
ports:
-containerPort:80
volumeMounts: #解释,把名称为cache-volume的卷(此处不在意卷的内容,具体内容由后续段落声明),挂载到pod的/cache目录;
-mountPath:/cache
name:cache-volume
volumes: #此段落解释为,把宿主机的/data/kubernetes声明为名称叫cache-volume的hostPath卷;
-name:cache-volume
hostPath:
path:/data/kubernetes
nfs等:网络存储卷;
允许将现有的NFS存储挂载到容器中,且不会像emptyDir那样易丢失,当删除pod时,nfs卷的内容会被保留,卷仅仅是被卸载,这意味着nfs卷可以预先准备好数据,之后启动pod即可直接使用,并且因为是网络共享存储,所以可以在多个pod中共享数据,也就是说nfs卷可以由多个pod同时挂载和读写;
测试nfs卷:需要自行搭建nfs系统,以下给出使用方法;
#测试nfs;
apiVersion:apps/v1
kind:Deployment
metadata:
name:nginx-deployment-site2
spec:
replicas:1
selector:
matchLabels:
app:ng-deploy-81
template:
metadata:
labels:
app:ng-deploy-81
spec:
containers:
-name:ng-deploy-81
image:nginx
ports:
-containerPort:80
volumeMounts:
-mountPath:/usr/share/nginx/html/pool1 #卷的挂载位置;
name:my-nfs-volume-pool1 #使用叫什么名字的卷;
-mountPath:/usr/share/nginx/html/pool2
name:my-nfs-volume-pool2
volumes:
-name:my-nfs-volume-pool1 #声明卷的名字;
nfs: #定义卷的类型;
server:172.31.7.109 #nfs服务地址;
path:/data/k8sdata/pool1 #nfs存储路径;
-name:my-nfs-volume-pool2
nfs:
server:172.31.7.109
path:/data/k8sdata/pool2
#为以上pod增加service;
apiVersion:v1
kind:Service
metadata:
name:ng-deploy-81
spec:
ports:
-name:http
port:80
targetPort:80
nodePort:30017
protocol:TCP
type:NodePort
selector:
app:ng-deploy-81
在负载均衡服务器安装并创建nfs;
# apt -y install nfs-server
# mkdir /data/k8sdata/pool1
# mkdir /data/k8sdata/pool2
# vim /etc/exports #配置nfs路径和权限;
/data/k8sdata/pool1 *(rw,no_root_squash)
/data/k8sdata/pool2 *(rw,no_root_squash)

# kubectl apply -f test-nfs.yaml
注意:在使用nfs文件系统的节点中需要安装nfs-common组件;