Kubernetes资源对象

  • json特点

- 不能注释
- 可读性较差
- 语法严格
- 比较适用于API返回值,也可用于配置文件(但一般没有用json格式)
- json格式
{"人员名单":
{"张三":{"年龄":18,"爱好":["看书","学习"]},
"李四":{"年龄":20,"爱好":["旅游","运动"]}
}
}
  • yaml文件特点

- 大小写敏感
- 使用缩进表示层级关系
- 缩进时不允许tab键,只允许使用空格
- 缩进空格数目不重要,同级元素左对齐即可
- 使用#表示注释,从这个字符到行尾,都会被解释器忽略
- 比json更适合做配置文件

k8s的设计理念

分层架构

 

 

 

k8s系统:核心层--应用层--管理层--接口层
k8s扩展:
- 作用于k8s内部:CRI CNI CSI 镜像仓库
- 作用于k8s外部:监控、日志收集、CI/CD、配置管理(如配置中心)等
无状态应用:相互之间没有依赖关系的应用,不需要角色选举,没有先后启动顺序,如nginx
有状态应用:之间需要选举或有先后启动顺序,如:mysql主从,zookeeper等

API设计原则

1、所有API应该是声明式的
2、高层API以操作意图为基础设计
3、低层API根据高层API的控制需要设计
4、尽量避免简单封装,不要有在外部API无法显示知道的内部隐藏机制(多个k8s集群,在k8s的api外封装一个api,管理所有的k8s集群,在外层reset,同步到不同集群的k8s)
5、API操作复杂度与对象数量成正比
6、API对象状态不能依赖于网络连接状态(如:1000个pod,按顺序部署,而不是1000个都好了之后才返回结果)
7、尽量避免让操作机制依赖全局状态,因为再分布式系统中要保证全局状态的同步是非常困难的(有些有过半机制,集群中一半的机器同步成功,就当同步成功,后面其他机器再慢慢同步)

API简介

内置API:部署好K8s后内置的api
自定义资源:CRD(Custom Resource Definition),部署k8s之后通过安装其他组件扩展出来的api

命名方式:
/apis/myapi/v1/pods
/分类/API组/API版本/资源对象
显示当前的api
# curl -cacert /etc/kubernetes/ssl/ca.pem -H "Authorization: Bearer TOKEN" https://127.0.0.1:6443
# curl -cacert /etc/kubernetes/ssl/ca.pem -H "Authorization: Bearer TOKEN" https://127.0.0.1:6443/具体api 可显示具体api的信息

 

 

 

资源类型

资源对象: pod、ReplicaSet、Node...
存储对象:Volume、PersistentVolume、PersistentVolumtClaim、Secret、ConfigMap
策略对象:SecurityContext、ResourceQuota、LimitRange
身份对象:ServiceAccount、Role、ClusterRole

 

 

 

常用命令

 

 

资源对象详解

yaml文件必备字段
1、apiVersion:创建该对象所使用的Kubernetes API
2、kind:想要创建的对象类型
3、metadata:定义识别对象唯一的数据,包括一个name、可选namespace
4、spec:定义资源对象的详细规范信息
5、status:Pod创建完成后k8s自动生成status状态

spec:声明的状态
status:实际的状态

Pod

1、k8s最小调度单元
2、一个Pod中可以运行一个或多个容器(多个容器共享一个网络名称空间)
3、运行多个容器的话,这些容器是一起被调度的
4、Pod的生命周期是短暂的,不会自愈
5、一般都是通过controller来管理和创建pod

job与cronjob

  • job使用场景

如:当我们部署了mysql,需要去初始化mysql的数据库数据表。但是进去后动太麻烦。就可以使用job,连接到对应数据库,使用job已经准备好的脚本进行初始化
特点:只执行一次,用完之后退出,不会启动,一般用于初始化环境
  • cornjob

周期性任务,如备份等
每次启动创建一个新容器
默认保留三个记录,超过三个删除最远的一次(三次记录为kubectl get pod 显示的cornjob的pod的数量)

控制器

RC/RS

  • Replication Controller 副本控制器

第一代控制器
匹配Pod不是通过标签去匹配的,是根据selector = != 严格匹配或取反
https://kubernetes.io/zh/docs/concepts/workloads/controllers/replicationcontroller/
https://kubernetes.io/zh/docs/concepts/overview/working-with-objects/labels/
  • ReplicaSet

第二代控制器
对选择器的支持(selector 还支持in notin)

Deployment

比rs更高一级的控制器,除了有rs的功能之外,还有很多的高级功能,比如最重要的,滚动升级、回滚 
但是deployment是管理replicaset控制器,再记录replicaset的版本
每次更新按25%当前pod数量更新pod

Service

解耦了宿主机到容器之间的关系

实现方式:通过label标签动态匹配后端的endpoint

ExternalName

将外部域名引入集群内部,而且可进行改名,让集群通过固定的service name访问集群外部的服务。有时也用于将不用namespace之间的pod通过该模式进行访问。en很少用到

ClusterIP

k8s集群内部能访问的ip
通过clusterip,内部服务需要调用时可访问clusterip,通过clusterip将请求转给自己负载的某个Pod
微服务常见手段:通过svc将pod全部注册到注册中心中,需要调用这个服务的服务,通过注册中心去获得需要提供服务的Pod地址

NodePort

将服务通过主机端口暴露,访问该暴露的主机端口去访问内部的服务

LoadBlance

通过lb类型的svc,与外部的负载均衡器进行关联,该负载均衡器有两个地址,公网地址和内网地址。由内网地址和k8s集群进行通信

跨节点nodePort转发路径

  • 目前状态,nginx服务为nodeport类型端口30012,有6个节点,3master 3worker(172.31.7.111~192.168.1.113),nginx在 .113节点上。

此时:访问192.168.1.1:30098时,流量路径

1、172.31.7.112接收到请求
2、根据路由规则(ipvsadm查看转到哪个ip上 10.200.218.92:80)
3、根据路由表(route -n)查看这个到IP的网关为 172.31.7.113(即下一跳地址) 网卡为tunl0
4、再看192.168.1.6的路由表,这个ip通过calicoxx网卡转发,后真正到达后端Pod
  • 112ipvsadm -Ln

 

 

 

 

  • 112路由表

 

 

 

 

  • 113路由表(到达Pod的网卡)

 

 

 

 

存储卷

Volume将容器中的指定数据和容器解耦,并将数据存储到指定位置,不同的存储卷功能不一样。如果是基于网络的存储卷可以实现容器的数据共享和持久化
静态存储卷需要在使用前手动创建PV和PVC,然后绑定至pod使用
  • 常用存储卷

- emptyDir:本地临时卷,容器被删除就没了。一般用于同一个Pod的多个容器数据共享(有些也可能有日志共享需求)
- hostPath:本地存储卷(但是跨主机的话,数据无法同步,如需要最好配置pod亲和性)
- configmap:配置文件,将配置文件挂载到指定的pod的路径
- secret:包含敏感信息的数据。如密码、令牌、密钥等对象
- nfs等(NAS、Ceph)

emptydir

当Pod呗分配给节点时,首先会创建emptyDir卷,并且只要该Pod在该节点上运行,该卷就会存在,正如卷的名字所属,他最初是空的,Pod中的容器可以读取和写入emptyDir卷中的相同文件,尽管该卷可以挂载在每个容器的相同或不同路径中,但当出于任何原因从节点中删除Pod时,emptydir中的数据将被永久删除。
路径:
/var/lib/kubelet/pods/$ID/volumes/kubernetes.io~empty-dir/cache-volume/$FILE

 

 

 

 

hotspath

将主机节点的文件系统中的文件或目录挂载到集群中,pod删除的时候,卷不会被删除。
但是当pod调度到另一主机的时候,数据无法跨主机同步,只存在第一次创建pod时调度的主机

NFS

nfs卷允许将现有的NFS共享挂载到容器中,不想emptyDir,当删除Pod时,nfs卷的内容将被保留,卷仅仅是被卸载,这意味着nfs卷可以预填充数据,并且可以在pod之间切换数据,nfs可以被多个写入者同时挂载
允许多个pod挂载一个nfs卷
允许一个pod挂载多个nfs卷

ubuntu下使用nfs协议挂载时,需要一个包:nfs-common 包含了一些nfs的lib库
没有的话:要么挂不上去,要么挂上去,传输速度会很慢

注意:
1、nfs共享时,配置文件写了一个目录,那么该目录下的所有子目录都可以单独挂载,不必子目录一个写一条配置
2、写nfs允许挂载的网段时,不要写pod的网段,否则宿主机是无法挂载的,那么容器也就无法挂载。
原因:pod的请求为了能原路返回,会以宿主机的ip去请求,并不会一pod的ip去请求
3、默认没有空间限制,需要去配置空间限制

PV/PVC

  • 简介

PV: PersistenVolume
PVC: PersistentVolumeClaim
用于实现Pod和storage解耦,这样我们修改storage的时候就不需要修改Pod。
与NFS的区别,可以在PV和PVC层面实现对存储服务的分配,存储的访问权限管理等。
k8s从1.0开始支持pv/pvc
不同存储卷支持的访问模式:

存储类型

静态存储

static:静态存储卷,需要在使用前手动创建pv,然后创建pvc绑定到pv。然后挂载到pod去使用,适用于pv和pvc相对比较固定的业务场景
dynamin:动态存储卷,先创建一个storageclass,后期pod在使用pvc的时候,可以通过存储类动态创建pvc,适用于有状态服务集群和mysql一主多从,zookeeper集群等

 

 

 

 

动态存储

https://kubernetes.io/zh/docs/concepts/storage/storage-classes/
https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
过程:
1、创建账户:
a.创建命名空间,保留nfs驱动程序(当使用到nfs动态存储时,会在目录下创建一个目录,供当前的pvc去使用,这些都需要进行交互)
b.创建服务账号ServiceAccount
c.创建ClusterRole
d.创建ClusterRoleBonding
2、创建storageclass(确定你的后端类型):
例如:
apiVersion: stroage.k8s.io/v1
kind: StroageClass
metadata:
name: example-nfs
previsioner:
server: nfs-server.example.com
path: /share
readOnly: "false"
注意:杰哥上课时的vers=4.1这个参数去掉了


3、创建NFS驱动

4、创建PVC
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: myserver0myapp-dynamic-pvc
namespace: myserver
spec:
storageClassName: managed-nfs-storage ##调用指定storageclass
addceeModes
- ReadWriteMany
resource:
  requests:
    storage: 500Mi
5、创建web服务

ConfigMap

ConfigMap配置信息和镜像解耦,实现方式为将配置信息放到ConfigMap中,然后在Pod中以Volume的形式挂载,从而实现导入配置
使用场景:
- 通过ConfigMap给Pod定义全局环境变量
- 通过ConfigMap给Pod传递命令行参数,如mysql -u -p的账户名可以通过configmap进行传递
- 通过ConfigMap给Pod中的容器服务提供配置文件,配置文件以挂载到容器的形式使用
注意事项:
ConfigMap需要在Pod使用之前创建
pod只能使用位于一个namespace的ConfigMap,及ConfigMap不能跨namespace使用
通常用于非安全加密的配置场景
ConfigMap通常是小于1MB的配置

 

 

 

 

 

Secret

  • 简介

功能类似于ConfigMap给Pod提供额外的配置信息,但是secret是一种包含少量敏感信息例如密码、令牌或密钥的对象

secret的名称必须是合法的DNS子域名

每个Secret的大小最多为1M,主要是为了避免用户创建非常大的Secret进而导致API服务器和kubelet内存耗尽,捕获创建很多小的secret也可能耗尽内存,可以使用资源配额来约束每个名称空间中的secret个数

再通过yaml文件创建secret时,可以设置data或stringData字段,data和stringData字段都是可选的,data字段中所有键值必须为base64编码的字符串,如果不希望执行这种base64字符串转换操作,也可以选择设置stringData字段,其中可以使用任何非加密字段的字符串作为其取值。

Pod可以用三种方式的任意一种来使用secret
作为挂载到一个或多个容器上的卷中文件(crt、key文件)
作为容器的环境变量
由kubelet在为Pod拉取镜像时使用(与镜像仓库的认证)

类型

Secret类型使用场景
Opaque 用户自定义数据
kubernetes.io/service-account-token ServiceAccount令牌
kubernetes.io/dockercfg ~/.dockercfg文件的序列化形式
kubernetes.io/dockerconfigjson ~/.docker/config.json文件的序列化形式
kubernetes.io/basic-auth 用于基本身份认证的凭据
kubernetes.io/ssh-auth 用于ssh身份认证的凭据
kubernetes.io/tls 用于TLS环境,保存crt证书和key证书
bootstrap.kubernetes.io/token 启动引导令牌数据

挂载流程

 

 

docker拉取镜像的secret

imagePullSecrets:
- name: 你创建的secret的名字
  • 镜像拉取流程

kubectl 发送创建pod指令,apiserver接收,将其存入etcd... 被调度到的节点的kubelet接收到指令,将secret发送到docker,docker携带者这个secret去私有镜像仓库拉取镜像

 

动态存储实验

创建服务账号并绑定

apiVersion: v1
kind: Namespace
metadata:
name: nfs
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
 # replace with namespace where provisioner is deployed
namespace: nfs
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["persistentvolumes"]
  verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
  resources: ["persistentvolumeclaims"]
  verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
  resources: ["storageclasses"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["events"]
  verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
  name: nfs-client-provisioner
   # replace with namespace where provisioner is deployed
  namespace: nfs
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
 # replace with namespace where provisioner is deployed
namespace: nfs
rules:
- apiGroups: [""]
  resources: ["endpoints"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
 # replace with namespace where provisioner is deployed
namespace: nfs
subjects:
- kind: ServiceAccount
  name: nfs-client-provisioner
   # replace with namespace where provisioner is deployed
  namespace: nfs
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
kubectl apply -f rbac.yaml

创建存储类

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-client
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # or choose another name, must match deployment's env PROVISIONER_NAME'
reclaimPolicy: Retain
mountOptions:
- noresvport   ##告知nfs客户端在重新建立网络连接时,使用新的传输控制协议源端口
- noatime   ##访问文件时不更新文件inode中的时间戳,高并发环境可提高性能
parameters:
archiveOnDelete: "true" ##删除pod时保留pod数据,默认为false时不保留数据
kubectl apply -f class.yaml

创建nfs控制器(控制创建pv)

kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-client-provisioner
namespace: nfs
spec:
replicas: 1
selector:
  matchLabels:
    app: nfs-client-provisioner
strategy:
  type: Recreate
template:
  metadata:
    labels:
      app: nfs-client-provisioner
  spec:
    serviceAccountName: nfs-client-provisioner
    containers:
      - name: nfs-client-provisioner
        image: 192.168.157.101/library/nfs-subdir-external-provisioner:v4.0.2
        volumeMounts:
          - name: nfs-client-root
            mountPath: /persistentvolumes
        env:
          - name: PROVISIONER_NAME
            value: k8s-sigs.io/nfs-subdir-external-provisioner
          - name: NFS_SERVER
            value: 192.168.157.19
          - name: NFS_PATH
            value: /dynamic-pv/nfs-client
    volumes:
      - name: nfs-client-root
        nfs:
          server: 192.168.157.19
          path: /dynamic-pv/nfs-client
# 部署自动创建pv管理nfs的deployment
kubectl apply -f deployment-nfs.yaml
# 查看日志
kubectl logs nfs-client-provisioner-cfbfd7fd5-kvkjr -nnfs

 

 

 

 

在nfs主机

vim /etc/exports
/dynamic-pv     192.168.157.0/24(rw,no_root_squash)
exportfs -arv

创建pvc

kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: my-pvc
namespace: magedu
spec:
storageClassName: nfs-client
accessModes:
- ReadWriteMany
resources:
  requests:
    storage: 500Mi
kubectl apply -f pvc.yaml

创建完后查看pvc

 

 

 

 

已为绑定状态

查看nfs下的目录

 

 

 

 

创建deployment测试pvc是否能够挂载

kind: Deployment
apiVersion: apps/v1
metadata:
name: ngixn
namespace: magedu
labels:
  app: nginx
spec:
replicas: 1
selector:
  matchLabels:
    app: nginx
template:
  metadata:
    labels:
      app: nginx
  spec:
    containers:
    - name: nginx
      image: 192.168.157.101/library/nginx:1.21.1
      volumeMounts:
      - mountPath: /usr/share/nginx/html/dynamic
        name: dynamic-pvc
    volumes:
    - name: dynamic-pvc
      persistentVolumeClaim:
        claimName: my-pvc
  • 挂载失败

当 mount -o noresvport <nfs 服务> 时,会碰到 Operation not permitted 问题,因为 nfs 默认配置选项是 secure,不允许客户端通过非特权端口访问。

如果客户端必须要 mount -o noresvport 访问,那么就需要 nfs 服务器配置允许非特权端口访问。需要修改 /etc/exports,设置 insecure 选项。

/etc/exports
/etc/exports 是 nfs 服务端的配置。nfs 客户端不读这个配置文件。

exportfs -s 查看 nfs 服务已加载的配置情况。

修改 /etc/exports 文件不会自动应用到当前 nfs,需要通过 exportfs -rv 重载。

原文链接:https://blog.csdn.net/kali_yao/article/details/120903104
  • 修改nfs配置文件

/dynamic-pv     192.168.157.0/24(rw,no_root_squash,insecure)

exportfs -arv
  • 重新挂载

1、删除pod
kubectl delete -f app-deployment.yaml
2、删除pvc
kubectl delete -f pvc.yaml
3、重新创建pvc
kubectl apply -f pvc.yaml
4、重新创建pod
kubectl apply -f app-deployment.yaml

 

 

 

posted @ 2022-05-06 14:17  wyllearning  阅读(154)  评论(0)    收藏  举报