k8s

发布时间 2023-09-11 14:47:50作者: 要快乐不要emo

k8s

1、为什么要使用k8s

了解架构对比:
	物理机: 将多个服务分配给一个机器,如果一个服务占用了大量资源,其余服务性能会下降
			将多个服务分开到不同机器,对资源浪费太厉害,成本太高
	虚拟机: 解决了应用之间运行在同一台物理机上对资源的争抢问题,每个虚拟机都拥有独立的操作系统
	容器:   和虚拟机类似,但是更为轻量,可以共享宿主机的操作系统,同时又拥有独立的系统,且资源相互隔离,由于分离了os与资源,可以跨平台移植
		优势:创建方便,一条命令即可创建,虚拟机相对来说太慢且繁琐
			 更为敏捷化:容器镜像是不可变的,可以频繁的进行构建部署和回滚
			 使运维和开发分离: 通常是在发布时构建容器而不是部署时,将应用与基础架构分离(通过ci/cd架构可以快速部署发布回滚)
			 可移植: 可以跨平台
			 可观察:提供os级别信息,以及应用程序的运行状况(进入容器就和一个独立的机器一样)
			 提高抽象度: 以前的应用发布在硬件之上的os上,需要关注这些信息,而容器只需要关注应用本身,运行在os之上(比如资源申请配置就可以达到)
			 松散耦合: 可以将服务拆分成多个微服务,而不是将一个服务运行在一个系统上
			 资源隔离: 可预估的资源使用(通过limit就可以知道这台机器最大使用多少资源)
			 资源利用更高效:
k8s的优势:
	管理容器化后的负载和服务
	可进行声明式配置和自动化(使用yaml文件,spec为声明,会自动化达到声明的状态)
	不是传统的paas平台提供服务,而是一个开源框架可以支持丰富的插件来自定义集群
# Kubernetes 包含了一组独立可组合的控制过程,可以持续地将当前状态驱动到所提供的预期状态

2、k8s功能

1、服务发现
使用dns服务来进行服务发现,coredns
2、负载均衡
可以针对流量进行负载均衡,svc对象
3、存储编排
可以自动挂载文件系统 ceph,nfs,nas,本地存储
4、自动部署和回滚
可以根据声明的状态,以自定义速率控制其状态,比如deploy
5、自动装箱
声明容器所需资源,不需要手动配置容器的资源,比如limit,request
6、自动修复
可以使用探针机制来自动重启那些不通过配置的容器,liveness,readyness
7、秘钥与配置管理
将明文或非明文转换为k8s对象 configmap

3、k8s概念

3.1 k8s对象

简介:Kubernetes对象 是持久化的实体,它们表示了一个抽象的集群的健康状态,描述了集群的下述信息
	1、容器化应用的运行状态 deploy,ds,
	2、可以被使用的资源 configmap
	3、应用运行时表现的策略 
	对象一经创建,那么系统将持续努力将状态达到其所共同描述的状态,可以理解为对象就是告诉K8S系统我们期望的集群状态
管理:
	1、声明式配置 yaml文件
	2、命令式 针对活动对象无法持久化保存,将在下次更替时消失,比如重拉pod

3.1.1 标签

# 到对象上的键值对集合、通常用来进行筛选,和多维度管理
root@k8-master1-ansible tomcat]# kubectl get pod -A -l app==tomcat
NAMESPACE   NAME                     READY   STATUS    RESTARTS   AGE
default     tomcat-d6d7b6985-qr4kp   1/1     Running   0          2m43s
kubectl get pod -A -l app!=tomcat

在yaml文件中用法
selector:
	matchLabels: # 与下面等价,当存在两个时需要满足&关系
	component: redis
	matchExpressions: # 同时存在多个时需满足与逻辑
    - { key: app, operator: In, values: [tomcat] } # 列表中可以有多个值, 
      { key: environment, operator: NotIn, values: [dev] }

3.1.2 注解

与标签类似,可以理解为对对象的一些注释,不可与命令交互

3.1.3 字段选择器

filed-selector
可以根据yaml文件中metadat,status的字段进行筛选
kubectl get statefulsets,services --all-namespaces --field-selector metadata.namespace!=default # 支持多种资源,选择
kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always # 支持多种条件筛选,满足与逻辑

3.1.4 Finalizers

    对一个对象进行标记,当与k8s集群进行交互要删除资源时,集群会先进行其定义的动作,完成动作后,将其字段清空,只有当其字段为空时k8s才会彻底删除你所需要删除的资源

3.2 租约

用来锁定共享资源并协调集合之内的成员之间的活动,常用于心跳检测和集群之间领导者选举

3.3 api对象

3.3.1 api术语

资源类型: 比如pod,service,deploy等,可以用在url中使用http调用,可以理解为类
针对资源类型的定义: 可以理解为资源类型的元数据信息,kind
资源|对象: 资源类型的实例
集合: 多个实例组成的列表
api对象一般都是指对具体资源的抽象化概念,代表了具体的实例,少数代指动作

3.3.2 url

# 核心资源
固定格式为/api/api对象版本-v1/集群级别|ns级别/namespace_name(如果是ns级别,需要指定ns名称)/api对象名称
# 非核心资源
/apis/group/version/namespace/namespace_name/资源类型 #ns级别的资源
/apis/group/version/资源类型 #集群级别的资源
# list 返回资源对象的集合
# 

4、k8s架构

4.1 节点

注册:
	自动注册: 使用kubelet向管控节点自动注册,需要开启对应选项 --register-node
	手动添加: 
	# 不管自动注册还是手动添加,k8s管控端会将节点表示为一个对象,若存在相同名称则k8s会将其视为同一个对象,当节点所有服务运行正常那么K8S集群会将其加入集群否则所有调度均会跳过此节点
    {
      "kind": "Node",
      "apiVersion": "v1",
      "metadata": {
        "name": "10.240.79.157",
        "labels": {
          "name": "my-first-k8s-node"
        }
      }
    }
节点状态详解:
[root@k8-node1 ~]# kubectl describe node 172.31.3.17
Name:               172.31.3.17  # 节点名称 由节点的内核报告
Roles:              node  # 节点角色 
Labels:             beta.kubernetes.io/arch=amd64  # 节点标签
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=172.31.3.17
                    kubernetes.io/os=linux
                    kubernetes.io/role=node
Annotations:        management.cattle.io/pod-limits: {"cpu":"1Gi","memory":"2Gi"}  # 节点注解
                    management.cattle.io/pod-requests: {"cpu":"425m","memory":"145Mi","pods":"5"}
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp:  Wed, 27 Jul 2022 19:50:11 +0800  # 节点创建时间
Taints:             <none>  
Unschedulable:      false
Lease:
  HolderIdentity:  172.31.3.17  
  AcquireTime:     <unset>
  RenewTime:       Fri, 14 Apr 2023 10:20:40 +0800
Conditions:   # 节点的详细running状况
  Type             Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
  ----             ------  -----------------                 ------------------                ------                       -------
  MemoryPressure   False   Fri, 14 Apr 2023 10:20:32 +0800   Sun, 02 Apr 2023 21:52:31 +0800   KubeletHasSufficientMemory   kubelet has sufficient memory available  # 内存压力 
  DiskPressure     False   Fri, 14 Apr 2023 10:20:32 +0800   Sun, 02 Apr 2023 21:52:31 +0800   KubeletHasNoDiskPressure     kubelet has no disk pressure  	 # 磁盘压力
  PIDPressure      False   Fri, 14 Apr 2023 10:20:32 +0800   Sun, 02 Apr 2023 21:52:31 +0800   KubeletHasSufficientPID      kubelet has sufficient PID available # pid压力  压力为True 代表节点资源相对不足
  Ready            True    Fri, 14 Apr 2023 10:20:32 +0800   Fri, 14 Apr 2023 08:58:37 +0800   KubeletReady                 kubelet is posting ready status  # 节点状态  Ready|False 表示节点不健康而且不能接收 Pod|Unknown 表示控制器最近没收到节点状态
Addresses:
  InternalIP:  172.31.3.17 # 通常是节点的仅可在集群内部路由的 IP 地址
  Hostname:    172.31.3.17  
Capacity:  # 节点总容量
  cpu:                8
  ephemeral-storage:  51175Mi
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             16247540Ki
  pods:               110
Allocatable: # 节点可供pod分配容量
  cpu:                8
  ephemeral-storage:  48294789041
  hugepages-1Gi:      0
  hugepages-2Mi:      0
  memory:             15530740Ki
  pods:               110
System Info: # 节点的一些os级别信息
  Machine ID:                 07dc04e68ae24ec6a7f9581b63af44a2
  System UUID:                71BF4D56-F1EE-DA55-1605-0F108EB76864
  Boot ID:                    82f6448c-a0b6-47dc-bc7e-05148be29929
  Kernel Version:             3.10.0-1160.71.1.el7.x86_64
  OS Image:                   CentOS Linux 7 (Core)
  Operating System:           linux
  Architecture:               amd64
  Container Runtime Version:  docker://20.10.5
  Kubelet Version:            v1.20.5
  Kube-Proxy Version:         v1.20.5
PodCIDR:                      10.160.192.0/18
PodCIDRs:                     10.160.192.0/18
Non-terminated Pods:          (5 in total)
  Namespace                   Name                                        CPU Requests  CPU Limits          Memory Requests  Memory Limits  AGE
  ---------                   ----                                        ------------  ----------          ---------------  -------------  ---
  cattle-system               cattle-cluster-agent-67c7fbfbc-5w74t        0 (0%)        0 (0%)              0 (0%)           0 (0%)         24d
  ingress-nginx               ingress-nginx-controller-54455d5f4-n69h2    100m (1%)     0 (0%)              90Mi (0%)        0 (0%)         26m
  kube-system                 calico-node-xkp9t                           250m (3%)     0 (0%)              0 (0%)           0 (0%)         24d
  kube-system                 node-local-dns-4glgk                        25m (0%)      0 (0%)              5Mi (0%)         0 (0%)         260d
  monitoring                  cadvisor-9ckxd                              50m (0%)      1Gi (13421772800%)  50Mi (0%)        2Gi (13%)      19h
Allocated resources: # 可分配资源的容量限制
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests    Limits
  --------           --------    ------
  cpu                425m (5%)   1Gi (13421772800%)
  memory             145Mi (0%)  2Gi (13%)
  ephemeral-storage  0 (0%)      0 (0%)
  hugepages-1Gi      0 (0%)      0 (0%)
  hugepages-2Mi      0 (0%)      0 (0%)
Events:              <none>

4.1.1 节点控制器

节点控制器属于控制器的一种,k8s控制平面的controll-manage组件内置多个控制器
# 功能
1、负载给其分配一个cidr网段
2、时刻关注节点运行状态,当节点不可用时将其从节点列表摘除
3、对节点进行健康检测,当节点状态为未知后默认五分钟开始进行节点上负载的驱逐
# 控制节点上工作负载的驱逐速率
# 资源容量跟踪,控制平面调度时需要保证节点的资源足够调度,需要时刻监控节点剩余资源

4.2 节点通信

4.2.1 节点到控制面的通信

![截图 2023-04-14 11-05-20](/home/gu/图片/截图/截图 2023-04-14 11-05-20.png)

4.2.2 控制面到节点的通信

1、控制面到节点
	a、控制面到节点kubelet
	获取pod的日志
	直接进入pod (exec)
	提供端口转发功能,将到kubelet的流量进行转发
	b、控制面到节点,pod,服务
	一般直接通过http协议进行传输,安全考虑可以使用ssh隧道或者Konnectivity 服务

4.3 控制器

控制器: 可以理解为一个非终止状态的控制回路,例如空间里有一个控制温度的传感器,会致力于将温度始终控制在期望的设定温度而不断努力
控制器至少追踪一种资源类型,这些资源表现为一个对象,拥有spec期望状态,而该资源的控制器通过与apiserver交互使其保持并接近期望状态
控制器通常包含一个无限循环的主循环,它会不断地观察Kubernetes API对象的状态,并根据需要对其进行操作

4.3.1 控制模式

1、通过与apiserver交互控制
比如job,deployment不直接控制pod的启动和停止,而是与api交互来启动或者删除pod
2、直接控制
一般用于集群外的资源,比如要保证集群中有足够的节点,那么控制器会与集群外的资源进行交互直接创建节点

4.3.2 自定义控制器

# 这是一个简单的控制器,实现当pod被删除时那么将删除日志输出
from kubernetes import client, config, watch
# 加载Kubernetes配置文件
config.load_kube_config()
# 创建Kubernetes API客户端
v1 = client.CoreV1Api()
# 创建一个监听器,监视Pod对象的状态
w = watch.Watch()
for event in w.stream(v1.list_pod_for_all_namespaces):
    # 如果Pod对象被删除,则打印日志
    if event['type'] == 'DELETED':
        print("Pod deleted: %s" % event['object'].metadata.name)

4.4 租约

租约主要有两个作用
1、用作集群间的领导者选举
2、提供类似于节点心跳的功能

4.5 垃圾收集

一种删除集群资源的机制统称,简单理解就是用来删除集群内各种资源的一种规则。
# 系统将会自动清理以下资源
1、已经终止的pod(api对象被清理的pod)
2、已完成的job(当job的生命周期被标记为已完成)
3、当定义了一个属主引用,此属主引用不在存在时此对象也会被删除
4、未使用的镜像和容器
5、动态创建的回收策略为delete的pv

4.6 容器

容器: 是一个可重复运行的,包含依赖环境在内的标准,通常可以跨os运行
容器镜像: 镜像是一个包含容器内应用运行所需所有环境和应用代码的软件包,其设计本身是无状态且不可变的,更改容器,请重新构建镜像
容器运行时: 容器运行的环境,负责容器运行的软件,常见的有docker和containerd

4.6.1 容器镜像

是一个封装了应用程序及其所需依赖环境的二进制数据,可以直接运行,但一般是将其上传到私有仓库然后在pod指定来使用

4.6.1.1 镜像更新

仓库中的镜像需要重新构建,构建完成后若需要更新pod中的镜像需要重新配置yaml文件,若名称相同则需要指定镜像拉去策略,默认为存在同名镜像则跳过拉取

4.6.1.2 镜像拉取策略

1、是否拉取
ifnotprensent 默认策略,存在同名镜像则跳过拉取
always 总是拉取
nerver 总不会拉取,若本地存在镜像则kubelet会创建,否则创建失败
2、镜像拉取策略
kubelet默认一次发送一个服务请求给镜像仓库,也就是说当节点存在多个pod时,镜像拉取默认是一个pod执行完成再执行另外一个pod,可以修改kubelet设置为多个pod同时拉取镜像,注意:pod中的多个镜像不支持同时拉取

4.6.2 私有仓库

我们常常使用私有仓库来存储镜像并在k8s中使用,私有仓库通常需要做账户认证

4.6.2.1 私有仓库认证

1、node节点方式
可以通过在node节点配置对私有仓库的认证来拉取镜像
2、使用secret
# 将下面的代码创建后kubectl apply -f 创建
apiVersion: v1
kind: Secret
metadata:
  name: docker-registy
data:
  .dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxNzIuMzEuMy4xNjYiOiB7CgkJCSJhdXRoIjogIllXUnRhVzQ2TVRJek5EVTIiCgkJfSwKCQkicXVhbmhlbmcuY29tIjogewoJCQkiYXV0aCI6ICJZV1J0YVc0Nk1USXpORFUyIgoJCX0KCX0KfQ==
type: kubernetes.io/dockerconfigjson

5、工作负载

简单来说就是k8s上面运行的应用程序
wget https://breezey-public.oss-cn-zhangjiakou.aliyuncs.com/softwares/linux/kubernetes/buildkit-v0.9.0.linux-amd64.tar.gz
tar xf buildkit-v0.9.0.linux-amd64.tar.gz -C /usr/local/

5.1 常见负载

1、deploy和rs
用来管理无状态应用,pod互相等价,需要时可以随时被替换
2、sts
用来管理有状态应用,各个pod之间所用数据相同且可以被固化,比如挂载远端存储
3、ds
用来在每个节点运行负载,可以给予label进行选择节点来运行,当有满足条件的节点加入,会自动运行负载
4、job,cornjob
定义一些一次性任务和计划任务

5.2 pod

k8s集群的最小调度单位,里面运行着一个或者多个容器

5.2.1 管理pod

# 运行模式
1、 一个pod封装一个容器,K8S集群直接管理pod
2、一个pod里面存在好多容器,比如由其中一个提供服务,其余容器提供数据的同步以及刷新(边车模式)
# 如果需要横向扩容可以使用控制器来运行多个相同的pod称之为副本

5.2.2 使用pod

可以通过控制器来控制pod的副本数目,进行pod资源管理
通过pod模版 pod.spec.template 来定义pod内容器的模版

5.2.2.1 为容器设置启动时的命令参数

apiVersion: v1
kind: Pod
metadata:
  name: alpine
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: quanheng.com/k8s/alpine:v2
    imagePullPolicy: IfNotPresent
    env: # 变量可以调用
    - name: MESSAGE
      value: "test message"
    - name: TEST2
      value: "10.182.3.1"
    - name: TEST3
      value: "2204"
    - name: TEST4
      value: "$(TEST2):$(TEST3)"
    command: ["/bin/sh"]
    args: ["-c","echo $(TEST4)"]

5.2.2.2 pod中容器的环境变量

env:
- name: MESSAGE
  valueFrom:
    fieldRef: # 将pod的信息传递给容器
      fieldPath: metadata.name
- name: MY_CPU_REQUEST
  valueFrom:
    resourceFieldRef: #将容器信息传递给容器里面作为变量
      containerName: test-container
      resource: requests.cpu

5.2.3 pod更新与替换

更新: 可以通过直接编辑yaml文件或者使用命令进行更改,后者通常会在下一次pod新建时失效
替换: 新建pod后会将旧的pod删除

5.2.4 静态pod

由kubelet管理的pod
在api服务器可见,但是不可对其进行管理
# 创建一个存放静态pod的目录
mkdir /root/staticpod
# 修改kubelet的配置文件 加上下面的配置
--pod-manifest-path=/root/staticpod
# 重启kubelet
systemctl daemon-reload && systemctl restart kubelet
# 增加和删除静态pod
kubelet 会定期扫描目录添加或删除pod

5.2.5 容器探针

由kubelet组件对容器进行一种探测的机制
可以由kubelet进行http或者socket探测,或者借助容器运行时 exec (进入pod内探测)
# 分类
liveness:存活探针,如果不通过则会将容器重启
readness:就绪探针,如果不通过则不会对外提供服务
# 探针方式
exec: 进入容器执行命令,若返回状态码为0则认为成功
http:通过get请求,返回状态码为200-399则认为成功
tcpsocket:通过ip+端口方式来查看,若端口打开则认为成功
grpc:远程调用响应状态为serving则认为成功

5.2.6 pod生命周期

1、调度pod到某节点,除非pod生命周期被终结否则将一直在其上
Pending(悬决)	Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间。
Running(运行中)	Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。
Succeeded(成功)	Pod 中的所有容器都已成功终止,并且不会再重启。
Failed(失败)	Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。
Unknown(未知)	因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。
# 容器状态
waiting:处于启动容器所需要的操作阶段,比如拉取镜像,挂载卷,通常可以通过describe看到其阶段
running:正常启动并运行
terminate:因为某些原因退出或失败,可以使用describe查看,通常有一个返回的状态码及说明

5.2.7 pod终止

当集群接收一个pod删除请求后
1、记录pod的体面终止周期,并将周期最后时间设为pod死期
2、在体面终止期间,kubelet发送term信号给容器内的主进程,若超过此期限则向所有容器发送kill信号,同时将pod状态转换为失败活删除成功
3、集群api进行强制删除,并将体面周期设为0
4、删除pod的api对象
# 强制删除
kubectl delete pod $pod_name --force --grace-period=0(将体面终结周期设为0,默认30)

5.2.8 init容器

init容器是一种特殊的容器,运行在pod内的应用容器之前,提供了应用容器内不存在的脚本和其他工具
# init容器与普通容器不同的点
1、总是运行到成功为止(当重启策略设置为never时直接判定失败)
2、当指定多个init容器,下一个启动前必须等待上一个成功启动才可以
3、init容器不支持探针
# 使用init容器的优势
1、开发者构建了一个容器,但部署时可能存在容器内缺少工具,或者需要导入一些自己使用的脚本等,没必要针对镜像重新构建,直接执行一个init容器即可
2、init容器具有不同于应用容器的文件系统,可以访问应用不能访问的secret
3、作为一种前置条件,可以指定一些事件,知道满足这些事件应用容器才可以启动
# 启动流程
1、init容器会在pod准备好网络和存储卷环境之后进行启动
2、根据定义的init容器按顺序依次启动,且必须等待上一个容器启动成功后才可以启动,若启动失败那么根据pod定义的重启策略进行重启或者直接判断pod启动失败
3、待init容器启动成功之后,应用容器将会启动
4、pod重启那么init容器也将会重新启动
5、注意: init容器的执行应该具有幂等性 pod中init容器应该名称唯一

5.2.9 pod干扰

# 非自愿干扰
pod因为某些意外事故被无故终结生命周期
比如
	最下层物理机故障
	虚拟机被误删或者因为意外情况消失
	内核错误
	网络错误导致节点被隔离从集群消失
	资源不足导致pod被驱逐
# 自愿干扰
具有主管行为的对pod资源进行删除或驱逐
比如
	删除deploy或者rs,sts,ds
	更新控制器导致pod重启
	直接删除pod
	排空节点,手动驱逐pod
	设置集群的自动伸缩,缩小集群节点
	移除一个pod,以允许其他pod来使用该节点
# 处理上述干扰(保证pod的高可用)
1、定义pod时设置request 和 limit值,以保证pod在被调度时节点拥有足够资源能供其使用
2、对于无状态和有状态应用使用deploy和sts来对pod进行多副本定义
3、通过亲和反亲和使pod跨机架或跨区域来进行调度,规避风险
4、使用pdb,k8s集群设置一种机制可以允许我们进行自愿干扰,比如控制器总是期望达成spec的期望目标数量,而pdb则定义pod拥有的最少数量,如果低于此数量那么具有干扰动作的命令将会被阻塞
5、使用qos

5.2.10 临时容器

pod是k8s集群的最小调度单位,通常pod创建后都是一次性且可以随时替换的,所以一旦被创建就无法新加入容器,而是通过控制器的方式来对pod进行添加容器的操作
# 临时容器
临时容器允许向现有的pod中添加一个容器
特点:
	没有端口配置
	资源分配是不可变的
	不能用作静态容器
	永远不会自动重启
用途 无法使用exec与其交互的容器对其进行交互式的故障排查

5.2.11 Qos 服务质量类

类似于进程中的优先级,当node没有足够的资源时,qos决定了那些pod是被优先驱逐的
# 分级
Guaranteed
	优先级最高,几乎不可能被驱逐
	不能超过自身的limit
	可以指定cpu管理策略来独占cpu
	要求:
		pod中的每个容器的cpu和内存都必须具有limit和request值且两值相等
Burstable
	优先级中等,在besteffort的pod都被驱逐后才会选择此类型pod
	由request,不需要设置limit,limit默认等于node资源
	优点是可以根据需求来灵活使用资源
	要求:
		pod中至少有一个容器cpu或者内存有request或limit
BestEffort
	优先级最低,优先被驱逐
	pod内容器没有limit和request
# 注意
qos是node节点负载不足时所发生的驱逐pod行为和其类似的还有如下集中但不归属qos
1、容器所需资源超过limit值
被kubelet干掉,不影响pod其他容器
2、容器运行资源超过定义的request值,且节点面临资源压力(pod的limit和request值等于容器之和)
pod将被驱逐,pod内容器都会被终止,通常不会在相同节点来进行重建
3、k8s集群进行调度时不会考虑qos,qos是在调度成功运行后节点所发生的行为

5.2.12 downloadAPI

这是一个允许容器在不适用k8s客户端和api的情况下获取自身或集群消息的机制
简单来说就是能使用此机制将pod中的字段以某种方式传递给容器来使用
方法:
	作为环境变量
	使用downloadapi作为卷中的文件
# filedRef
传递pod级别的信息,一般为元数据信息,或者spec中指定的主机信息
# resourceRef
传递spec.container级别的信息,一般为资源限制的值或者

5.3 deployment

功能:控制器的一种,主要为pod和rs提供声明式更新的能力
	以受控的速率更新
	可以通过穿件新的rs来更新或者删除现有的deploy创建新的来接收旧的资源
工作原理:
	创建时:deploy会直接创建一个rs,将其副本数设置为指定数量,来控制创建对应数量的pod
	更新时:deploy会新建一个rs,新的rs将每次以指定的速率来创建pod,当新的pod就绪时删除对应的旧的pod继续创建下一个pod,直至替换完成后将旧的rs删除
使用方式:
1、创建一个deploy,deploy会新建一个rs,rs会创建pod
2、更新现有deploy的podspectemplate,新的rs将会被创建,deploy会以受控速率将pod从旧的rs迁移到新的
3、回滚deploy
4、扩大deploy规模
5、暂停deploy上线,修改templatespec,使用新的版本上线
6、通过deploy状态判断是否存在停滞
7、清理旧的rs

5.3.1 创建一个deploy

# 这是一个副本数为3的nginx deploy,指定容器端口映射到主机端口的10845
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: nginx-app
  name: nginx-app # 这是其控制的rs的命名规范基础
spec:
  revisionHistoryLimit: 10 # 指定更新版本要保留的历史版本数量
  strategy: # 指定滚动更新策略
    rollingUpdate: # 当type为rollingupdate时使用此设置
      maxSurge: 1 # 最大超出deploy数量的值,支持百分比 比如deploy的副本数量为10 那么最大为11
      maxUnavailable: 1 #最大不可用的值,支持百分比 
    type: RollingUpdate
  replicas: 3  # 注意若使用hpa控制器来控制那么此处不设置
  selector: #  指定了rs所要管理的pod
    matchLabels: 
      run: nginx-app # 比如这个例子是指定了具有run=nginx-app的lable的pod 注意控制器给定的标签尽量不要冲突,否则可能会造成一些冲突和未知结果
  template:
    metadata:
      labels: # 这里定义的lable就是上面rs所要管理的pod的lable 这是一个简单的lable,可以支持更为复杂的标签选择机制
        run: nginx-app
    spec:
      containers:
      - image: quanheng.com/k8s/nginx:1.18
        name: nginx-app
        ports:
          - containerPort: 80
            hostPort: 10845
            protocol: TCP
      dnsPolicy: ClusterFirst
      restartPolicy: Always
[root@k8-master1-ansible deploy]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
nginx-app-bc967656c   3         3         3       5m7s

5.3.2 更新deploy

有三种方法
1、使用kubectl命令来更新
kubectl set image deployment/${deploy名称} ${pod名称}=新镜像地址
kubectl set image deployment/nginx-app nginx-app=quanheng.com/k8s/nginx:1.19
2、使用kubectl edit来编辑配置文件
kubectl edit deployment/${deploy名称}
3、直接便捷yaml文件然后apply

5.3.3 回滚deploy

# 查看更新历史
kubectl rollout history deployment/${deploy名称}
# 查看指定的更新详细信息 
kubectl rollout history deployment/${deploy名称} --revision=2
# 回滚
	命令: kubectl rollout undo deployment/${deploy名称} # 这个命令是回滚到上一版本,注意如果再次使用会回到当前版本而不是继续往回

5.3.4 对控制器进行扩/缩容

# 手动
kubectl scale deployment/${deploy名称} --replicas=${num}
# 自动
需要有metric-server支持,以cpu和内存的利用率为标准进行自动扩缩容
kubectl autoscale deployment/${deploy名称} --min=${num} --max=${num} --cpu-percent=50
# 比例缩放

5.3.5 暂停和恢复上线

# 暂停
kubectl rollout pause deployment/nginx-app
# 暂停和恢复中间可以对deploy进行更改配置而不触发其更新,直到执行恢复命令
# 恢复
kubectl rollout resume deployment/nginx-deployment

5.4 replicaset

功能:维护一组pod的正常运行
rs会获取与其选择算法相符合的pod资源信息,并将其纳入自己的管理之内,比如自己创建了两个pod指定了和rs选择算法相同的标签,那么会立即被纳入管理
应用:
	通过更改标签将pod从rs中移除来进行排查等,这种移除方式会出发新建一个pod
	通过更改副本数来扩缩容
	可以被hpa管理
	推荐使用deploy来替代rs

5.4.1 新建一个rs

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx-app
        image: quanheng.com/k8s/nginx:1.18

5.5 sts

# 功能:专门管理有状态服务的一个控制器,和deploy类似不同点在于
1、提供持久存储
2、提供持久标识符
简单来说,sts可以针对那些需要持久化存储的应用来进行设置,假如pod挂掉那么不管怎么调度新起的pod总是会使用原来的存储对象
# 适用场景:
有下列需求的使用sts
稳定的、唯一的网络标识符。
稳定的、持久的存储。
有序的、优雅的部署和扩缩。
有序的、自动的滚动更新
# 使用须知
1、需要向存储类申请创建pv来进行挂载
2、需要自己创建网络标识 # 一般拥有固定的名称来满足集群内dns的解析
	名称格式: sts名称-有序序号
	解析规则: $(pod_name).$(服务名称).$(名字空间).svc.cluster.local
3、删除sts时不提供可靠性保证,最好的办法是先缩容到0
4、执行更新时可能需要人为干预才能修复一些受损状态
综上所述,如果不是有需求使用最好还是使用deploy这种无状态的pod更为方便

5.5.1 sts案例

apiVersion: v1
kind: Service
metadata:
  name: nginx # svc名称
  labels:
    app: nginx # svc标签
spec:
  ports:
  - port: 80  # svc端口
    name: web # svc端口名称
  clusterIP: None # 指定此svc为无头服务
  selector: # 选择app=nginx的lable进行转发
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web # sts名称
spec:
  selector:
    matchLabels:
      app: nginx # 必须匹配 .spec.template.metadata.labels
  serviceName: "nginx" 
  replicas: 3 # 默认值是 1
  minReadySeconds: 10 # 最短需要容器未崩溃多少s的时间来开始进入就绪态
  template:
    metadata:
      labels:
        app: nginx # 必须匹配 .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: registry.k8s.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 1Gi

5.5.2 sts扩缩机制

stspod和普通pod有些区别
1、启停
sts_pod启动安装0-1-n的顺序,停止则反序
2、扩缩容
sts_pod 扩容时 它前面所有序号的pod必须依次序处于running否则不会启动新的pod
缩容时,如果前面的pod没有running那么后面的pod不会停止,直到前面的podrunning后才会停止
3、更新
.spec.updateStrategy
  OnDelete # 修改sts配置后必须手动删除旧的pod才会触发更新
  RollingUpdate # 修改后会自动更新
    partition: num # 声明一个序号,序号以上的被更新,以下的不被更新,常用作金丝雀发布或分阶段上线

5.5.3 sts pvc回收策略

.spec.persistentVolumeClaimRetentionPolicy # 此字段控制是否以及如何删除pvc 使用此功能api服务器需要开启自动删除pvc功能
whenDeleted #当删除sts的策略
  Delete #删除
    sts 将属主引用放在其pvc上当sts删除时,pvc因为没有属主会被垃圾回收期回收
  Retain(默认)
whenScaled #当缩减sts时的策略
  Delete
	sts 将对比期望数目与pod总数,然后删除多余的pod,并将删除pod作为pvc的属主引用,以删除这些pvc
# 当pod崩溃时不适用以上策略
当sts重新启动后需要等待其属主引用的更新,若不等待其更新建议自己有能力管理pvc的属主引用,否则会导致一些问题

5.6 daemonset

简介: 管理运行在所有集群节点上同一副本的一种控制器,当新节点加入会自动在新节点运行ds所控制的副本
用法:
  守护进程
  日志收集
  监控服务

5.6.1 案例

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: cadvisor
  namespace: monitoring
spec:
  selector:
    matchLabels:
      name: cadvisor
  template:
    metadata:
      labels:
        name: cadvisor
    spec:
      nodeSelector: # 指定选择器
        matchLabels:
          lb: nginx
      affinity: #指定亲和
        matchLabels:
          lb: nginx
      hostPID: true
      tolerations: # 指定标签使其不对其调度
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      containers:
        - name: cadvisor
          image: quanheng.com/k8s/cadvisor:v0.37
          command:
              - /usr/bin/cadvisor
              #- --port=8080
              - --housekeeping_interval=1s
              - --logtostderr=true
              - --docker_only=true
          ports:
          - containerPort: 8080
            hostPort: 10088
            protocol: TCP
          resources:
            requests:
              cpu: 50m
              memory: 50Mi
            limits:
              cpu: 1Gi
              memory: 2Gi

5.7 job

简介: job将会创建一个或者多个pod,直到指定数量的pod成功终止,跟踪记录成功完成的pod数量,当达到指定个数时,job结束
适用范围:
1、非并行的pod,一般启动一个pod完成即为结束
2、指定成功完成个数的job .spec.completions = n(计数模式),当成功完成的个数等于n时job完成
   可以指定.spec.completionMode="Indexed" 为job中的pod指定一个索引
3、指定.spec.parallelism=n 争抢模式
   多个pod被启动,以争抢模式开始运行,完成N条任务后,每个pod都可以随时成功退出,一旦其成功退出,其余pod立即结束进程并退出,所有pod退出后,job完成
4、job终止
	.spec.backoffLimit 指定pod或容器失败其值会累加,当超出此值则job失败
	.spec.activeDeadlineSeconds 手动指定一个生命周期,默认s 当达到此时间限制那么job立即终止
5、job清理
	.spec.ttlSecondsAfterFinished 指定一个时间,结束后n秒将会被级联删除

5.8 cronjob

5.8.1 案例

# 周期性的执行job
apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "* * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: quanheng/k8s/alpine:v2
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

6、存储

6.1 卷

概念:容器中的文件都是临时性的,当我们删除容器时,那么容器中的文件也会随之消失,卷的概念就是为了解决持久化存储的

6.2 卷的类型

6.2.1 cephfs


6.2.2 configmap

主要向pod提供配置文件

6.2.3 downwardAPI

引用pod或容器级别的字段作为变量或文件,还可使用secret和configmap
volumes:
    - name: podinfo
      downwardAPI:
        items: # 定义多个文件
          - path: "labels" # 文件名称
            fieldRef: # 使用pod级别信息作为文件
              fieldPath: metadata.labels # 文件名称内容
          - path: "annotations"
            resourceFieldRef: # 使用容器级别信息 仅支持下面三个字段
              containerName: client-container 
              resource: requests.cpu
              divisor: 1m

6.2.4 emptydir

# 当pod因为某些原因从节点移除时那么此目录中数据会被清除,如果仅仅是容器重启,那么数据不会消失

6.2.5 hostpath

hostpath允许容器使用主机的文件系统,将宿主机的某目录或文件挂载进容器
# 注意
hostpath使用具有一定的安全风险,请将挂载权限设置为只读,并且如果有可能尽量不适用此方式挂载
# 常见用法
1、将/var/lib/docker挂载到容器中,那么此容器就具有访问docker内部机制的权限
2、运行cadvisor,需要将/sys 目录挂载进容器
3、指定挂载的路径在容器创建前是否存在,以什么方式和形式存在 # 比如必须满足某路径存在某类型文件才可以继续,需要为其指定type来满足此条件
如果不知道type那么默认不会对挂载路径进行任何检查
DirectoryOrCreate	如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为 0755,具有与 kubelet 相同的组和属主信息。
# 如果使用此模式进行挂载,文件必须存在父目录,挂载时要分开挂载,分别定义父目录和文件进行挂载
Directory			在给定路径上必须存在的目录。
FileOrCreate		如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为 0644,具有与 kubelet 相同的组和所有权。
File				在给定路径上必须存在的文件。
Socket				在给定路径上必须存在的 UNIX 套接字。
CharDevice			在给定路径上必须存在的字符设备。
BlockDevice			在给定路径上必须存在的块设备

6.2.6 NFS

应该是应用最多的挂载文件系统,将网络存储挂载进pod里,nfs可以被多个pod挂载以实现文件共享,pod被删除nfs文件系统将被卸载

6.2.7 pv

6.2.8 rbd

基于ceph的存储,作为块设备被挂载,有点是可以被任意格式化为想要的文件系统,且pod在被删除时候,块设备只是被卸载,持久化保存数据

6.2.9 secret

将K8S对象中的secret作为文件挂载进容器,主要提供秘钥管理,且以tmpfs挂载进入,不会持久存储
# 创建secret 常用与私有仓库配置拉取镜像,ssh秘钥,自身需要加密的账号密码等
echo "" |base64 -d
kubectl create secret generic test-secret --from-literal='username=my-app' --from-literal='password=39528$vdg7Jb'
volumes:
    - name: secret-volume
      secret:
        secretName: test-secret

6.2.10 subpath

当pod中有多容器时候,可以挂载一个卷,使用subpath分别使用此卷下的不同子目录
subPathExpr: $(POD_NAME) 可以使用downloadapi来获取pod的名称作为变量使用

6.3 持久卷(PV)

简介: pv系统为k8s集群使用存储提供一组api,让使用者将卷的制备和使用进行分离弱化对卷的制备

6.3.1 pv

pv是集群中的存储,可以自己进行制备或者通过存储类来进行制备(存储类:存储资源的统称集合,可以通过调用直接生成同一类型的存储),pv属于集群资源,类似于pod这种资源一样,通过插件实现,记录了pv的细节,后端是各种其他文件系统,比如nfs,ceph,lvm等

6.3.2 pvc

pvc是指对pv资源的请求,比如pv定义了一个400G的存储,pvc指可以从上面申请多少空间存储进行使用,同时指定对该存储空间的访问模式,回收策略等

6.3.3 pv申领和生命周期

6.3.3.1 制备

制备分为动态和静态
静态:自己制备
动态:基于一个存储类来实现对卷的实时制备,不需要提前制备,当需要时会通过存储类制备

6.3.3.2 binding

将pvc与pv实现绑定效果,才可以使用存储,只有满足匹配条件才可以进行binding,未binding的pvc不可以使用

6.3.3.3 使用

当pvc成功申领并和pv进行binding那么就可以将其作为卷进行挂载使用

6.3.3.4 回收

当pvc被使用时,无法直接删除此pvc,需要等待其finalizers列表为空,同理当pvc与pv进行binding且正在被使用,无法删除pv需等待pv与pvc的binding关系解除才可以删除pv
对pv对象进行回收策略定义,当与其binding的pvc不再使用时,可以选择以下策略
回收
	此pv可以继续使用,将数据擦除
保留
	保留上一个卷留下的数据,需要删除pv重新创建
删除
	删除上一个卷留下的数据,需要删除pv重新创建

6.3.4 案例

apiVersion: v1
kind: PersistentVolume 
metadata:
  name: nginx-pv
spec:
  capacity: # 定义卷容量大小
    storage: 5Gi
  volumeMode: Filesystem # 指定卷为文件系统或块存储
  accessModes: # 指定访问模式
    - ReadWriteOnce # 仅支持一个节点读写
    - ReadOnlyMany # 支持多个节点只读
    - ReadWriteMany # 支持多个节点读写
    - ReadWriteOncePod # 支持一个pod进行读写
  persistentVolumeReclaimPolicy: Recycle # 指定此pv回收策略
  storageClassName: slow # 指定存储类的名称
  mountOptions: # 挂载选项
    - hard
    - nfsvers=4.1
  nfs: # 指定使用的后端存储
    path: /tmp
    server: 172.31.3.111
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 2Gi
  storageClassName: slow # 若不设置此字段那么pvc会对没有卷类型属性的pv进行申领,若设置了默认存储类,那么会选择到默认存储类
  selector: # 选择卷的匹配标签
    matchLabels: 
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}

6.3.5 StorageClass

pv可以指定归属于某个存储类,若不指定,对于申请特定类的pvc将无法对其进行binding
# 用于动态制备pv,是所有同一类型的pv的制备器
# 案例
cephrbd
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/rbd #制备器 用于指定插件制定对应的pv
parameters: # 配置
  monitors: 10.16.153.105:6789
  adminId: kube
  adminSecretName: ceph-secret
  adminSecretNamespace: kube-system
  pool: kube
  userId: kube
  userSecretName: ceph-secret-user
  userSecretNamespace: default
  fsType: ext4 # 指定块设备初始化的文件系统
  imageFormat: "2"
  imageFeatures: "layering"
reclaimPolicy: Retain # 设置回收策略
allowVolumeExpansion: true # 是否允许卷进行动态扩展 支持csi和rbd
mountOptions: # 挂载选项
  - debug
volumeBindingMode: Immediate

---
nfs
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: example-nfs
provisioner: example.com/external-nfs # 指定制备器
parameters: # 配置
  server: nfs-server.example.com # nfs服务器地址
  path: /share # nfs服务路径
  readOnly: "false" # 权限
  
  
--- 
本地
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

6.3.6 pv生命周期

Available(可用)-- 卷是一个空闲资源,尚未绑定到任何申领;
Bound(已绑定)-- 该卷已经绑定到某申领;
Released(已释放)-- 所绑定的申领已被删除,但是资源尚未被集群回收;
Failed(失败)-- 卷的自动回收操作失败。

6.3.7 使用本地存储作为pvc

apiVersion: v1
kind: PersistentVolume
metadata:
  name: block-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  volumeMode: Block
  persistentVolumeReclaimPolicy: Retain
  fc:
    targetWWNs: ["50060e801049cfd1"]
    lun: 0
    readOnly: false
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: block-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Block
  resources:
    requests:
      storage: 10Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-block-volume
spec:
  containers:
    - name: fc-container
      image: fedora:26
      command: ["/bin/sh", "-c"]
      args: [ "tail -f /dev/null" ]
      volumeDevices: # 使用方式为在容器内挂载此块设备而非作为文件系统
        - name: data
          devicePath: /dev/xvda
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: block-pvc

6.4 投射卷

可以将secret,downwardAPI,configMap,serviceAccountToken映射到一个目录下
# 案例
apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: container-test
    image: busybox:1.28
    volumeMounts:
    - name: all-in-one
      mountPath: "/projected-volume"
      readOnly: true
  volumes:
  - name: all-in-one
    projected: # 指定卷格式为投射卷模式
      sources: 
      - secret: # 多个以数组形式排列
          name: mysecret
          items:
            - key: username
              path: my-group/my-username
      - downwardAPI:
          items:
            - path: "labels"
              fieldRef:
                fieldPath: metadata.labels
            - path: "cpu_limit"
              resourceFieldRef:
                containerName: container-test
                resource: limits.cpu
      - configMap:
          name: myconfigmap
          items:
            - key: config
              path: my-group/my-config

6.5 动态制备卷

简介:允许按需制备存储卷,无需实现进行制备
原理: 由k8s的StorageClass API组件进行实现,通过调用api对象,api对象指定的有对应的存储制备商或第三方提供的关于要制备的卷的信息及参数,当使用此api时由制备器提供参数完成制备,无需手动进行制备

6.5.1 案例

# 定义一个存储类
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd
# 指定pvc的存储类,当需要时会自动创建
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim1
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast
  resources:
    requests:
      storage: 30Gi

6.5.2 默认存储类

可以通过开启apiserver中的DefaultStorageClass来使用默认存储类,
通过对类进行注解
storageclass.kubernetes.io/is-default-class=ture
当不指定任何类时那么会默认从默认类申请

7、servic

7.1、k8s网络模型

k8s pod中容器共享网络和存储,pod内的容器通信通过localhost,容器与容器直接需要协调端口如何使用
# 集群网络功能
1、使用本地回环网络来进行容器直接的通信
2、pod-pod之间的通信
3、svc允许暴露pod中运行的应用程序,svc也支持发布仅供内部集群使用的服务
4、ingress提供暴露http,网站,和api的功能

![](/home/gu/图片/截图/截图 2023-04-24 15-55-37.png)

7.2 svc功能

1、将运行在pod中的应用暴露为网络服务
2、将一组被其他服务依赖的pod暴露给对应服务
3、提供负载均衡功能

7.3 svc负载均衡

后端转发功能

7.3.1 带选择算符

# 带选择算符
apiVersion: v1 #api版本
kind: Service #资源名称
metadata: #元数据信息
  name: nginx-svc #资源名称
  namespace: test1 #资源所属ns
spec: #资源定义
  selector:  # 指定具有以下lable的pod作为选择范围
    run: nginx-app
  #type: ClusterIP #用于k8s内部集群,是一个虚拟ip 通过ipvs进行转发 默认选项,不手动指定则由系统分发
  type: NodePort # 使用宿主机端口
  #type: loadbalace使用外界负载均衡来完成转发,需要同时设置clusterip和nodeport
  sessionAffinity: ClientIP #会话亲和,可指定ClientIP表示将同一地址的请求转发到同一个pod
  #sessionAffinityConfig:
  #  clientIP:
  #    timeoutSeconds: 10800
  ports: # svc需要暴露的端口列表
  - port: 1666 #svc的监听端口
    hostPort: 4512 # 暴露服务所在的宿主机端口以访问服务
    targetPort: 80 # 转发到后端的pod端口号

7.3.2 endpointslice

# 不带选择算符 使用endpointsslice
# 通常和上面svc联合使用可以实现如下功能
1、用来使用集群外资源
2、访问其他ns下的服务
3、迁移到k8s,仅在集群运行一部分后端服务
# 注意,不能见ep转发给另外一个svc,只可转发给服务
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
---
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
  name: my-service-1 # 按惯例将服务的名称用作 EndpointSlice 名称的前缀
  labels:
    # 你应设置 "kubernetes.io/service-name" 标签。
    # 可以使用此标签使用
    kubernetes.io/service-name: my-service # 从哪个svc接收流量
addressType: IPv4
ports: # 转发到哪个端口
  - name: '' # 留空,因为 port 9376 未被 IANA 分配为已注册端口
    appProtocol: http # 为后端应用定义协议
    protocol: TCP
    port: 9376
endpoints: # 转发到哪个ip
  - addresses:
      - "10.4.5.6" # 此列表中的 IP 地址可以按任何顺序显示
      - "10.1.2.3"

7.3.3 无头服务

不使用负载均衡和指定集群ip,如何进行负载均衡和路由取决于dns设置
1、带有标签选择的svc
k8s会创建一个endpoint对象
2、不带有标签的svc(依赖dns解析)
对于 type: ExternalName 服务,查找和配置其 CNAME 记录  自定义解析记录
对所有其他类型的服务,针对 Service 的就绪端点的所有 IP 地址,查找和配置 DNS A / AAAA 条记录

7.3.4 svc总结

1、带选择算符的svc
应用最多,也是最常见的方式,用来对集群进行负载均衡
2、endpointslice
自定义流量转发路径,可以将流量转发到集群外的服务上或其他ns下的服务,不可以指定转发到其他svc
3、无头服务
可以指定选择算法,来生成endpoint对象,将其通过dns解析为ip,直接打到后端pod
不指定选择算法,默认使用dns来对名称进行解析

7.4 svc暴露

7.4.1 cluster ip

将svc暴露为集群ip并指定端口,可以在集群内通过集群ip+端口方式访问后端应用,这是默认暴露类型,可以通过ingress来将其暴露到集群外

7.4.2 nodePort

# 直接将后端服务通过节点上的端口进行暴露
apiVersion: v1
kind: Service
metadata:
  name: tomcat
spec:
  selector:
    app: tomcat
  type: NodePort
  ports:
  - name: tomcat
    protocol: TCP
    port: 1764
    targetPort: 8080
    nodePort: 10087

7.4.3 loadblance

用于外接负载均衡器接收流量,再将流量转发给后端应用

7.4.4 ExternalName

# 当访问svc时将其转发到自定义的域名上
# 一般用来转发到集群外的服务上
apiVersion: v1
kind: Service
metadata:
  name: test
  namespace: prod
spec:
  type: ExternalName
  externalName: my.database.example.com

7.4.5 外部ip

# 指定将此svc绑定到外部ip上在集群内可以通过外部ip + svc端口来访问集群内服务
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: MyApp
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 49152
  externalIPs:
    - 198.51.100.32

7.5 ingress

简介:一个将svc暴露为http或https接口的组件
功能:
1、提供一个可以访问的url
2、提供负载均衡功能
3、基于名称的虚拟托管
4、终止ssl和tls
# 注: 使用ingress需要先安装对应的控制器

7.5.1 ingress模版-nginx

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx" # 指定ingress类的名称,表示使用哪一个类的ingress
    nginx.ingress.kubernetes.io/use-regex: 'true' # 使用正则匹配
    nginx.ingress.kubernetes.io/proxy-connect-timeout: '600' 
    nginx.ingress.kubernetes.io/proxy-send-timeout: '600'
    nginx.ingress.kubernetes.io/proxy-read-timeout: '600'
    nginx.ingress.kubernetes.io/proxy-body-size: '50m'
    nginx.ingress.kubernetes.io/rewrite-target: / # 将所有未知路径重定向 
    nginx.ingress.kubernetes.io/app-root: /index.html # 根路径页面
spec:
  rules: # ingress规则定义
  - host: www.heng.com # 针对域名,可以定义多个
    http:                                                                          
      paths:
      - pathType: Prefix
        path: / # 指定域名后的路径
        backend: # 当访问时将其转发给哪个后端svc
          service:
            name: nginx-svc 
            port: 
              number: 1666
      - pathType: Prefix
        path: /app1 # 可以定义不同路径
        backend:
          service:
            name: tomcat
            port: 
              number: 1764

7.5.2 ingress 类

# ingress可以由不同的类实现,每个ingress应该指定一个类的归属
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: external-lb
spec:
  controller: k8s.io/ingress-controller # 定义类由哪个控制器实现
  parameters:
    apiGroup: k8s.example.com
    kind: IngressParameters
    name: external-lb
# 作用域问题
类的作用域默认是集群范围,也可以指定为ns范围

7.5.3 默认后端

ingress将会把未知的流量转发到默认的后端服务
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress0
spec:
  defaultBackend:
    service:
      name: test
      port:
        number: 80

7.6 网络策略

简介: 用于控制pod的准入和准出流量,相当于对pod做iptables规则

7.6.1 隔离类型

# 默认情况下所有的pod都是默认没有隔离政策的
出口隔离: egress 列表中的是出口隔离 
	当指定出口隔离时,仅允许与出口隔离定义的ip列表进行通信
入口隔离: ingress 列表中的是入口隔离
	当指定入口隔离时,仅允许与出口隔离定义的ip列表进行通信
如果通信双方都存在隔离政策,那么都必须要进行放行

7.6.2 案例


apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector: # 针对那些pod,使用lables来进行选择
    matchLabels:
      role: db
  policyTypes: # 针对这些pod进行什么类型隔离,可以同时指定入口和出口
    - Ingress
    - Egress
  ingress: # 定义入口隔离策略 可以理解为谁可以访问我的哪个端口
    - from:
        - ipBlock: # 包含那些ip或网段
            cidr: 172.17.0.0/16 
            except: # 从上述ip或网段中去除的ip或网段
              - 172.17.1.0/24
        - namespaceSelector: # 针对那些ns
            matchLabels:
              project: myproject
        - podSelector: # 针对哪些pod
            matchLabels:
              role: frontend
      ports: # 针对端口及端口的流量协议
        - protocol: TCP
          port: 6379
          endport: 6900 # 可以形成一个端口范围
  egress: # 定义出口策略 可以理解为我可以访问谁的哪个端口,可以定义多个ip或网段
    - to:
        - ipBlock:
            cidr: 10.0.0.0/24
      ports:
        - protocol: TCP
          port: 5978

7.6.3 策略选择

定义在to和from内
podSelector: 指定同ns下的pod
namespaceSelector: 指定特定ns下的所有pod
namespaceSelector 和 podSelector: 指定特定ns下的特定pod 这是一个组合条件 注意和 并列条件的区别

8、配置

8.1 configmap

8.1.1 简介

configmap主要用来将非机密的数据用键值对来进行保存,常用来作为 命令行参数,环境变量,或者存储卷中的配置文件

8.1.2 类型

# 键值对
apiVersion: v1
kind: ConfigMap
metadata:
  name: cm-kv
data:
  # 类属性键;每一个键都映射到一个简单的值
  player_initial_lives: "3"
  ui_properties_file_name: "user-interface.properties"

# 文件
apiVersion: v1
kind: ConfigMap
metadata:
  name: cm-file
data:
  # 类文件键
  game.properties: | # 文件1 :前面为文件名称
    enemy.types=aliens,monsters
    player.maximum-lives=5    
  user-interface.properties: | # 文件2
    color.good=purple
    color.bad=yellow
    allow.textmode=true

8.1.3 使用

8.1.3.1 变量和作为文件挂载

# 用作容器命令和参数
apiVersion: v1
kind: Pod
metadata:
  name: configmap-demo-pod
spec:
  containers:
    - name: demo
      image: alpine
      command: ["sleep", "3600"]
      env:
        # 定义环境变量
        - name: PLAYER_INITIAL_LIVES # 请注意这里和 ConfigMap 中的键名是不一样的
          valueFrom:
            configMapKeyRef:
              name: game-demo           # 这个值来自 ConfigMap
              key: player_initial_lives # 需要取值的键
        - name: UI_PROPERTIES_FILE_NAME
          valueFrom:
            configMapKeyRef:
              name: game-demo # 在pod中的变量名字
              key: ui_properties_file_name # pod中的变量的值对应的cm的key
      volumeMounts:
      - name: config
        mountPath: "/config"
        readOnly: true
  volumes:
  # 你可以在 Pod 级别设置卷,然后将其挂载到 Pod 内的容器中
  - name: config
    configMap:
      # 提供你想要挂载的 ConfigMap 的名字
      name: game-demo
      # 来自 ConfigMap 的一组键,将被创建为文件
      items:
      - key: "game.properties"  # cm定义的文件名称
        path: "game.properties" # 挂载后显示的文件名称
      - key: "user-interface.properties"
        path: "user-interface.properties"

8.2 secret

8.2.1 简介

和cm类似,但是可以对对象进行加密,通常使用base64,常用来作为秘钥挂载

8.2.2 使用

# 作为文件挂载 配置在voluemount
# 作为容器的环境变量 配置在env[].valuefrom.secretkey
# 作为拉取镜像的凭证 配置在spec.imagePullSecrets
secret作为文件被使用时,会周期性的刷新,当更新secret时容器内的文件也会更新

8.2.3 创建

# kubectl 
kubectl create secret generic db-user-pass \
    --from-literal=username=admin \
    --from-literal=password='Fulifang@123'
kubectl create secret generic db-user-pass \
    --from-file=username=./username.txt \
    --from-file=password=./password.txt

8.2.4 查看

kubectl get secret $secret -ojsonpath='{.data}'
echo $message |base64 -d

8.2.5 使用场景

# 作为容器的环境变量
env:                                                                            
  - name: cm-kv
      valueFrom:
        configMapKeyRef:
          name: cm-kv
          key: name
# 带ssh秘钥
创建: kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/root/.ssh/id_rsa --from-file=ssh-publickey=/root/.ssh/id_rsa.pub

8.3 资源限制

8.3.1 简介

资源限制是指对pod在节点上的资源使用做限制使其只能使用规定的资源包含request和limit,一个是规定pod最小使用量,一个是最大使用量,若不规定那么pod会尽可能多的占用资源

8.3.2 资源单位

# cpu
cpu单位为1 或 200m 前者表示1个cpu后者表示0.2个cpu cpu表示计算资源,为绝对值,不管运行在什么样的配置上表示的算力相同
cpu单位表示一个权重值,若需要对节点资源进行争抢,那么权重大的pod将会获得更多的使用时间
# 内存
内存单位为M 或Mi  略有区别但大致相同 Mi表示2的幂数
内存限制容器对资源的请求当超过其限制时触发oom机制

8.4 kubeconfig 文件

8.4.1 简介

kubeconfig文件指与集群api通信所需的一些认证机制信息的文件,而不是名称为kubeconfig的文件
默认使用当前家目录下的.kube/的config文件

8.4.2 上下文

context
包含cluster , namespace, user
可以使用 kubectl  config use-context 来设置默认

8.5 kustomize

定制 Kubernetes 配置的工具
1、从其他来源生成kubernetes资源
2、组织和定制资源集合,基于现有资源或者定制新的资源成为集合
3、为资源设置贯穿性

9、安全

9.1 云原生安全简介

云,集群,容器,代码

9.1.1 云

# 云服务商
# 基础设施
网络访问api: 不允许将集群暴露在网络,应且定义一个列表用来使用网络访问控制列表控制谁可以访问
node: 尽可能不将node暴露给网络,应使用loadbalance,nodeport等集群类型服务进行连接,且最好仅能从控制平面节点连接
etcd: 仅允许控制平面且通过tls进行访问
etcd数据加密: 将etcd进行静态加密

9.1.2 集群

# 可配置的集群组件
# 运行在集群中的程序
采用rbac授权
使用secret进行加密
定义应用的qos
定义pod网络策略
定义ingress的tls

9.1.3 容器

容器漏洞扫描
镜像签名
以最低权限操作容器尽量避免特权用户
使用强隔离能力的容器运行时

9.1.4 代码

通过tls进行加密访问
限制端口通信范围
定期对依赖库进行扫描
静态代码扫描分析
动态检测攻击

9.2 service account


9.3 api 访问控制

1、api服务器监听在非本机的6443端口,本机使用443端口,api服务器可以使用ca证书进行签名认证,如果使用私有证书需要在访问kubeconfig文件中添加签名的ca证书副本,当客户端访问时在此阶段可以进行tls验证
2、通过tls认证后进行http认证,可以启用多个认证模块,任意一个满足即可,认证通过后认证该用户为某username
客户端证书,账号密码,普通令牌,引导令牌,json web令牌等
3、鉴权,通过http认证后,会对username进行鉴权,授予对应权限给改用户,比如操作,查看,删除集群资源等
4、准入控制

9.4 基于rbac的访问控制

9.4.1 简介

集群中,应尽量减少特权配置的分发,尽量给每个人分配最小权限

9.4.2 实践

9.4.2.1 sa

# 创建sa
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins
  namespace:jenkins
# 创建权限
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: jenkins
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create","delete","get","list","patch","update","watch"]
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get","list","watch"]
- apiGroups: [""]
  resources: ["events"]
  verbs: ["watch"]
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get"]
# 将权限绑定到sa
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: jenkins
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: jenkins
subjects:
- kind: ServiceAccount
  name: jenkins
# 1.22版本之后需要手动管理secret生成永久token 
apiVersion: v1
kind: Secret
metadata:
  name: nginx-sa-secret
  namespace: vm
  annotations:
    kubernetes.io/service-account.name: nginx
type: kubernetes.io/service-account-token
# 创建kubeconfig
kubectl config view > config
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED # 集群ca
    server: https://172.31.3.10:6443
  name: cluster2 #自定义集群名称
contexts:
- context:
    cluster: cluster2
    user: nginx
  name: nginx@cluster2
current-context: nginx@cluster2
kind: Config
preferences: {}
users:
- name: nginx
  user:
    token: 
token=kubectl get secrets -n vm nginx-sa-secret -ojsonpath='{.data.token}'|base64 -d

9.4.2.2 用户账号

# 创建证书
umask 077; openssl genrsa -out guquanheng.key 2048
openssl req -new -key guquanheng.key -out guquanheng.csr -subj "/CN=guquanheng"
# 签名
openssl x509 -req -in guquanheng.csr -CA /etc/kubernetes/ssl/ca.pem -CAkey /etc/kubernetes/ssl/ca-key.pem -CAcreateserial -out guquanheng.crt -days 3650
# 生成kubeconfig
kubectl config set-credentials guquanheng --client-certificate=guquanheng.crt --client-key=guquanheng.key --embed-certs=true --kubeconfig=./config 
kubectl config set-context guquanheng@kubernetes --cluster=kubernetes --user=guquanheng  --kubeconfig=./config
kubectl config set-cluster kubernetes --server=https://172.31.3.10:6443 --certificate-authority=/etc/kubernetes/ssl/ca.pem --kubeconfig=./config

# 创建权限
# 将权限与用户账号绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: my-clusterrole-binding
subjects:
- kind: ServiceAccount
  name: nginx
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: istiod-istio-system
  apiGroup: rbac.authorization.k8s.io

10、策略

10.1 limitrange

针对ns级别的资源限制 通常指单个用户对集群各个ns的利用
实现对ns内pod或容器的最小和最大的资源使用量限制
实现对ns内pvc申请的最小和最大的使用限制
实现对ns内计算资源的默认配置,当拉起容器时自动配置limit和request
# 创建默认的limitrange
# 若存在默认的请求和限制的值,如果指定请求而不指定限制,那么会使用默认值,若指定了限制而不指定请求,那么请求等于限制
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limit-range
spec:
  limits:
  - default:
      cpu: 1
      memory: 1Gi
    defaultRequest:
      cpu: 500m
      memory: 512Mi
    type: Container
# 创建pod 可以看到会自动注入limit和request
# 创建默认的ns中容器可以使用的最大或最小值
# 定义了pod所用资源必须在此区间范围内,若超出或小于均不会被调度
apiVersion: v1
kind: LimitRange
metadata:
  name: mem-min-max-demo-lr
  namespace: sed
spec:
  limits:
  - max:
      memory: 1Gi
    min:
      memory: 500Mi
    type: Container

10.2 requestquota

针对ns级别的资源进行最大资源使用量进行限制 通常针对多用户,对用户使用资源进行限制
# 创建一个配额  定义了pod数量,请求和限制之和,pvc数量,svcload类型数量,nodeport类型数量
pods"	Pod
"services"	Service
"replicationcontrollers"	ReplicationController
"resourcequotas"	ResourceQuota
"secrets"	Secret
"configmaps"	ConfigMap
"persistentvolumeclaims"	PersistentVolumeClaim
"services.nodeports"	NodePort 类型的 Service
"services.loadbalancers"	LoadBalancer 类型的 Service
---
apiVersion: v1 
kind: ResourceQuota
metadata:
  name: compute-resources
  namespace: sed
spec:
  hard:
    pods: "2" 
    requests.cpu: "500m"
    requests.memory: 500Mi
    limits.cpu: "1"
    limits.memory: 2Gi
    persistentvolumeclaims: "1"
    services.loadbalancers: "2"
    services.nodeports: "0"

10.3 进程id限制

针对容器的pid进行限制,可以限制使用数量或者预留一部分进程id给系统调度使用

11、调度,抢占,驱逐

11.1 调度

调度,是指当有一个新建pod的请求被下发,k8s通过watch机制发现未被调度的pod,通过一些列算法,这个pod调度到合适的节点,由kubelet进行拉起容器的操作

11.1.1 kube-scheduler

属于控制面的一个组件主要负责将pod绑定到对应的节点上进行运行
绑定: 选出最佳调度节点,将其通知给apiserver的过程

11.1.1.1 调度策略

1、过滤
根据条件选出适合的节点
2、打分
从适合的节点中选出最优节点

11.1.2 指派pod到指定节点

11.1.2.1 lable算法

通过lable机制作为选择算法,使pod能调度到对应节点

11.1.2.2 节点亲和/反亲和

可以定义满足某条件接收调度或尽量满足某条件进行调度

11.1.2.3 pod亲和/反亲和

可以依据已经运行的pod标签来进行选择 

11.1.2.4 nodename

直接指定pod运行在哪个节点上

11.1.3 污点和容忍度

11.1.3.1 简介

污点: 和节点亲和相反,排斥特定条件的pod
污点规则: 
NoSchedule: 禁止调度
PreferNoSchedule: 尽量不调度,若其他节点不满足调度条件,最后调度到此节点
NoExecute:禁止调度且当节点存在具有相同lable的pod对其进行驱逐
kubectl taint node worker-01  testv1=testk1:NoSchedule # 打污点 具有testv1=testk1的pod不调度到此节点
kubectl taint node worker-01  testv1=testk1:NoSchedule- # 解除污点 
容忍: 允许pod调度到对应污点的节点
tolerations: # 定义容忍存在key1=value1的lable的污点节点
- key: "key1"
  operator: "Equal" # 指定必须kv值对应才可满足
  value: "value1"
  effect: "NoSchedule"
tolerations: # 定义存在key1 的key的lable的污点节点
- key: "key1" # 若key为空 表示可以容忍任何污点
  operator: "Exists" # 只要存在key,不需要匹配任何value值
  effect: "NoSchedule" # 若effect为空,则容忍所有key为key1的污点
  
# 节点可以存在多个污点,pod可以存在多个容忍,当容忍都匹配后节点仍存在污点,那么会继续按照剩下的污点来进行调度

11.1.3.2 用法

# 实现专用节点
# 配备特殊硬件的节点
# 基于污点进行驱逐

11.2 抢占

11.2.1 优先级

PriorityClass 
# k8s 资源的一种 用来设置优先级 值越大,优先级越高
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass # 资源类型
metadata: 
  name: high-priority-nonpreempting
value: 1000000 # 指定优先级
preemptionPolicy: Never 
globalDefault: false #是否将其设置为默认优先级,集群中可以且仅允许存在一个默认优先级,若不设置 默认为0
description: "This priority class will not cause other pods to be preempted." # 针对此优先级加一个描述,用来说明此优先级的使用场景
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  priorityClassName: high-priority #在pod或deploy等控制器模版中可以指定优先级对象名称来使用定义的优先级
优先级用来针对pod调度起作用,当大量pending pod开始被调度时,优先级最高的pod可以优先获得调度

11.2.2 抢占

当集群中pod其余优先级功能,若调度过程存在资源不足需要争抢,那么优先级高的pod会选择一个节点体面终止低于其优先级的一个或多个pod,进而进行调度,当我们使用控制器指定pod因干扰而留下的最小数量时pdb,抢占调度优先级高于pdb仍会将其驱逐,当存在多个节点符合条件 会驱逐优先级最低的,当优先级最低的具有pdb那么会依次向上选择最低的

11.3 驱逐

# 节点压力驱逐
# api主动驱逐

12、k8s 组件

12.1 kube-sceduler

调度器 
# 工作原理
当kube-sceduler通过watch机制检测到集群存在未调度pod时,开始进行调度流程 这一过程称之为 绑定
1、过滤出集群中可被调度的node节点
2、为所有可调度的node节点打分
3、选出最高分来运行pod
4、将其通知给apiserver

13、集群管理

13.1 证书

13.2 管理资源

1、可以在yaml文件中定义多个资源 使用 --- 进行分割
2、创建资源指定文件时可以指定多个 -f xx.yaml -f xxx.yaml
3、可以直接使用url源使用 -f https://xx.xx.yaml
4、链式操作 使用$() 或者 xargs 来进行传参操作
5、管理标签  kubectl lables pods -l app=nginx 
6、管理副本 kubectl scale deployment/my-nginx --replicas=1

13.3 日志管理

13.4 插件

13.4.1 calico

13.4.1.1 k8s网络模型

# 每个pod都有自己的ip地址
# pod内的容器共享ip地址,并且可以互相通信
# pod可以使用podip与其他集群中的pod通信无需nat
# 隔离是使用网络策略定义的
可以理解为 pod 类似于 vm虚拟机 而pod中的容器就像虚拟机中的进程一样

13.4.1.2 插件功能

# 将pod连接到网络
# 管理podip分配

13.5 hpa


14、扩展

14.1 operator

自定义资源的控制器

14.2 coredns

14.2.1 coredns配置解析

# corefile
  Corefile: |
    .:53 {
    	log #将解析记录以日志形式输出到容器日志
        errors # 错误记录到标准输出
        health { # 在本地8080端口提供健康报告 为容器提供存活探针
            lameduck 5s
        }
        ready # 在本地8181提供一个端口当可以提供服务时访问此端口会返回200 为容器提供就绪探针
        # kubernetes 基于pod的ip来应答dns查询
        kubernetes cluster.local in-addr.arpa ip6.arpa { 
            pods insecure # 与kube-dns进行兼容
            fallthrough in-addr.arpa ip6.arpa
            ttl 30
        }
        prometheus :9153 # 将coredns的度量指标以prom格式暴露给指定端口
        # 不在kubernetes集群域内的查询将会被转发到下列指定路径
        forward . /etc/resolv.conf { 
            max_concurrent 1000
        }
        cache 30 # 前段缓存30s
        reload # 允许自动加载配置文件,更改cm后2分钟生效
        loadbalance # 随机分配A AAAA MX
    }

14.2.2 coredns问题排查

# 排查思路
1、进入pod内使用nslookup 看是否可以进行解析
2、查看/etc/resolve
3、查看dnspod是否正常,查看pod日志
4、查看svc是否正常,ep是否正常

14.3 CRD 扩展资源

14.3.1 扩展api

apiVersion: apiextensions.k8s.io/v1 # 注意这里的 apiVersion
kind: CustomResourceDefinition # 注意这里的 kind
metadata:  
  name: subnets.quanheng.com # 名字必需与下面的 spec 字段匹配,并且格式为 '<名称的复数形式>.<组名>'
spec:  
  group: quanheng.com # 组名称,用于 REST API: /apis/<组>/<版本>  
  versions: # 列举此 CustomResourceDefinition 所支持的版本
    - name: v1 # 版本名称,用于 REST API: /apis/<组>/<版本>
      served: true  # 每个版本都可以通过 served 标志来独立启用或禁止 
      storage: true # 其中一个且只有一个版本必需被标记为存储版本
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                cronSpec:
                  type: string
                image:
                  type: string
                replicas:
                  type: integer 
  scope: Cluster # 可以是 Namespaced 或 Cluster
  names:
    plural: subnets # 名称的复数形式,用于 URL:/apis/<组>/<版本>/<名称的复数形式>
    singular: subnet # 名称的单数形式,作为命令行使用时和显示时的别名
    kind: Subnet # kind 通常是单数形式的驼峰命名(CamelCased)形式。你的资源清单会使用这一形式。
    shortNames: # shortNames 允许你在命令行使用较短的字符串来匹配资源
    - sn

14.3.2 扩展对象


15 、API调用

15.1 python

# 连接到kubernetes集群并获取客户端
from kubernetes import client, config
config.load_kube_config(r'/home/gu/桌面/git/kubernetes/config')
v1=client.CoreV1Api() 
# 基于yaml文件中的key值来进行获取资源
resouces=v1.ret = v1.list_pod_for_all_namespaces(watch=False) --> 返回一个k8s资源对象列表
# 使用items方法转化为python列表对象
resouce_list=resouces.items
# resouce_list可以将yaml文件中的 key值当做其方法来使用,从而获取资源对象数据
for i in resouce_list:
	print(i.metadata.name)

15.2 kubectl

15.2.1 常用命令

events 获取集群事件
diff 将配置文件与正在运行的资源做比对

get
# 排序
sort-by 将获取到的资源以指定对象排序输出,支持jsonpath格式
kubectl get pods --sort-by='.status.containerStatuses[0].restartCount'
# 指定标签获取
-l 
# 指定条件获取,比如指定一个对象其键名包含-而不是_

15.2.2 格式化输出

# 自定义输出列,基于yaml文件来输出自定义列,不指定名称默认输出所有的资源,多列中间以,隔开
-o custom-columns
kubectl get pods <pod-name> -o custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion
# 以文件形式来实现,和上面结果一样
cat templete.txt
NAME          RSRC
metadata.name metadata.resourceVersion
kubectl get pods <pod-name> -o custom-columns-file=template.txt
# jsonpath
表达式
@ 表示当前对象
.或者[] 子运算符,表示基于当前运算符进行的运算
[,] 并集运算符,通常用来获取同一维度资源下的多个资源,比如获取当前资源的名称和资源限制
* 通配符,获取所有对象
range end 迭代列表

15.2.3 kubectl命令插件

# 可以以任何语言进行编写,以kubectl-开头的文件,加执行权限后添加到PATH变量
cat kubectl-hello
#/bin/bash
echo hello

15.2.4 自动补全

yum -y install bash-completion 
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

16、etcd

16.1 etcd备份

# 备份
ETCDCTL_API=3 etcdctl --endpoints $ENDPOINT snapshot save snapshotdb
ETCDCTL_API=3 etcdctl                                                                           
  --endpoints=https://$etcd_nodeip:2379 \
  --cacert=/path/ssl/ca.pem \
  --cert=/path/ssl/etcd.pem \
  --key=/path/ssl/etcd-key.pem \
  snapshot save snapshot.db
# 查看备份
etcdctl --write-out=table /path/snapshot status snapshotdb
# 恢复
etcdctl snapshot restore --data-dir /path/data snapshotdb

17、问题管理

17.1 问题求助

17.2 故障排查

17.2.1 pod

# 查看 Pod 的当前状态和最近的事件
kubectl describe pod 
# pending 状态
1、pod未被调度,调度所需资源不足
2、使用了hostport端口冲突
# wating 状态
调度成功,但无法正常运行,常见于镜像拉取失败
# crash 状态
# running但没有正常工作
大概率时yaml文件出错可以使用validate 选项重建pod kubectl apply --validate -f mypod.yaml 

17.2.2 svc

svc 是集群中进行pod负载均衡的,会建立对应的ep,当出问题可以先排查ep看是否被创建,若没有ep,查看svc的选择算符,列出pod,并验证pod是否归属svc
# 是否存在网络策略影响
# 是否存在于同一ns
# dns服务是否正常,能否正常解析
# 是否可以通过ip访问svc
# kube-proxy是否正常运行

17.2.3 dns

pod内dns指向不是集群内的dns地址
查看kubelet配置文件或启动参数中dns地址,将其修改为与本机一样
https://www.cnblogs.com/chaojiyingxiong/p/16999461.html