拉勾教育——kubernetes

时间:Oct. 24, 2021 分类:

目录:

历史问题

性价比低,资源利用率低

有时候只是希望运行一些简单的程序而已,比如跑一个小进程,为了不相互影响,就要建立虚拟机,会浪费不少资源,同时操作也比较复杂,花费时间也会比较长

迁移成本高

想要迁移整个自己的服务程序,就要迁移整个虚拟机

环境不一致

进行业务部署发布的过程中,服务之间的各种依赖,比如操作系统、开发语言及其版本、依赖的库/包等,都给业务开发和升级带来很大的制约

docker的出现,镜像解决了环境打包的问题,打包的是整个操作系统或者依赖环境

但是容器的编排调度还是有很多的问题

  • 调度 自动生成实例
  • 反亲和 实例之间相邻/相隔
  • 健康检测 自动检测实例状态
  • 容错 在健康节点生成新的实例
  • 可扩展 根据需要添加删除实例
  • 网络 实例通信
  • 服务发现 实例注册和发现
  • 滚动升级 实例升级和回滚

kubernetes采用pod+label的方式

相关容器组合成Pod,被共同部署和调度,形成服务

  • 容器内多进程,生命周期不好管理
  • pod管理多容器,很好的隔离资源

master主动请求node,由master做流控

Kubernetes 中定义了如下三种重启策略,可以通过spec.restartPolicy字段在Pod定义中进行设置

  • Always 表示一直重启,这也是默认的重启策略。Kubelet 会定期查询容器的状态,一旦某个容器处于退出状态,就对其执行重启操作;
  • OnFailure 表示只有在容器异常退出,即退出码不为 0 时,才会对其进行重启操作;
  • Never 表示从不重启;

startupProbe探针状态为Success之前,其他所有探针都处于无效状态,直到它成功后其他探针才起作用

定义了多个Handler,则会按照Exec、HTTPGet、TCPSocket的优先级顺序

  • PostStart 可以在容器启动之后就执行。但需要注意的是,此 hook 和容器里的 ENTRYPOINT 命令的执行顺序是不确定的。
  • PreStop 则在容器被终止之前被执行,是一种阻塞式的方式。执行完成后,Kubelet 才真正开始销毁容器。

kubectl get pods -l

kubectl get pods -l environment=production,tier=frontend
kubectl get pods -l 'environment in (production),tier in (frontend)'

statefulset

StatefulSet的RollingUpdate更新策略还支持通过partition参数来分段更新一个StatefulSet。所有序号大于或者等于partition的Pod都将被更新

kubectl create secret

$ kubectl create secret -n demo docker-registry regcred \
   --docker-server=yourprivateregistry.com \
   --docker-username=allen \
   --docker-password=mypassw0rd \
--docker-email=allen@example.com
 secret/regcred created
 $ kubectl get secret -n demo regcred
 NAME      TYPE                             DATA   AGE
 regcred   kubernetes.io/dockerconfigjson   1      28s

downloadAPI

$ cat downwardapi-volume-demo.yaml
apiVersion: v1
kind: Pod
metadata:
   name: downwardapi-volume-demo
   namespace: demo
   labels:
      zone: us-east-coast
      cluster: downward-api-test-cluster1
      rack: rack-123
   annotations:
      annotation1: "345"
      annotation2: "456"
spec:
   containers:
      - name: volume-test-container
         image: busybox:1.28
         command: ["sh", "-c"]
         args:
         - while true; do
               if [[ -e /etc/podinfo/labels ]]; then
                  echo -en '\n\n'; cat /etc/podinfo/labels; fi;
               if [[ -e /etc/podinfo/annotations ]]; then
                  echo -en '\n\n'; cat /etc/podinfo/annotations; fi;
               sleep 5;
            done;
         volumeMounts:
            - name: podinfo
               mountPath: /etc/podinfo
   volumes:
      - name: podinfo
         downwardAPI:
            items:
               - path: "labels"
                  fieldRef:
                     fieldPath: metadata.labels
               - path: "annotations"
                  fieldRef:
                     fieldPath: metadata.annotations

PV

遵循FlexVolume约定的接口规范,放置到/usr/libexec/kubernetes/kubelet-plugins/volume/exec/,kubelet通过exec方式调用,以命令行参数为输入,返回Json格式结果

FlexVolume因为有局限性

  • 需要一些前置依赖包,像ceph就需要安装ceph-common等依赖包
  • 部署很麻烦,而且往往需要很高的执行权限,要可以访问宿主机上的根文件系统

所以CSI采用了容器化部署

apiVersion: v1 kind: PersistentVolume metadata: name: task-pv-volume # pv 的名字 labels: # pv 的一些label type: local spec: storageClassName: manual capacity: # 该 pv 的容量 storage: 10Gi accessModes: # 该 pv 的接入模式 - ReadWriteOnce hostPath: # 该 pv 使用的 hostpath 类型,还支持通过 CSI 接入其他 plugin path: "/mnt/data"

PV 一般会有如下五种状态:

  • Pending 表示目前该 PV 在后端存储系统中还没创建完成
  • Available 即闲置可用状态,这个时候还没有被绑定到任何 PVC 上
  • Bound 就像上面例子里似的,这个时候已经绑定到某个 PVC 上了
  • Released 表示已经绑定的 PVC 已经被删掉了,但资源还未被回收掉
  • Failed 表示回收失败

同样,对于 PVC 来说,也有如下三种状态:

  • Pending 表示还未绑定任何 PV
  • Bound 表示已经和某个 PV 进行了绑定
  • Lost 表示关联的 PV 失联

service

ClusterIP,还有 NodePort、LoadBalancer 和 ExternalName

DaemonSet

DaemonSet Pod 依然由 DaemonSetsController 进行创建,但是不预先指定spec.nodeName了,而通过节点的亲和性,交由默认调度器进行调度

监控

  • cAdvisor
  • metrics-server 一个集群范围内的监控数据聚合工具
  • Kube-state-metrics 监听kube-apiserver中的数据,并生成有关资源对象的新的状态指标,比如Deployment、Node、Pod

权限

  • 认证
  • 授权
  • 准入控制

--token-auth-file静态token 创建一个ServiceAccount的时候,kube-controller-manager会自动帮你创建出一个Secret来保存Token

HTTP请求的Header为

Authorization: Bearer <TOKEN>

资源限制

LimitRange 限定CPU和Memory的申请范围 ResourceQuota namespace内的资源总量进行限制

GC

  • Kubelet 会对容器每分钟执行一次GC操作,对容器镜像每5分钟执行一次GC操作
  • Kubernetes 内部对象的GC,例如replicaSet根据ownerReferences所属于Deployment,级联关系删除策略deleteOptions.propagationPolicy这个字段,来控制删除的策略,取值包括上Orphan、Foreground或者Background

PriorityClass调度优先级

调度器如何扩展

efficiency-bservice-shop、sfgateway-api、delivery-check和rideraccount

CRI、CNI和CSI

自定义对象

自定义对象的方式

  • 聚合API
  • CRD

聚合API可以将访问请求转发到后端用户自己的扩展APIServer

apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
  name: v1alpha1.wardle.example.com # 对象名称
spec:
  insecureSkipTLSVerify: true
  group: wardle.example.com # 扩展 Apiserver 的 API group 名称
  groupPriorityMinimum: 1000 # APIService 对对应 group 的优先级
  versionPriority: 15 # 优先考虑 version 在 group 中的排序
  service:
    name: myapi # 扩展 Apiserver 服务的 name
    namespace: wardle # 扩展 Apiserver 服务的 namespace 
  version: v1alpha1 # 扩展 Apiserver 的 API version

在 kube-apiserver中创建一个 API 对象组,其对应的组(Group)为 wardle.example.com,版本号为 v1alpha1。创建成功后,我们就可以通过 /apis/wardle.example.com/v1alpha1 这个路径访问了。至于这个对象组里提供了哪些对象,就需要我们在扩展的 APIServer 中声明出来了。

那 kube-apiserver 又是怎么知道将 /apis/wardle.example.com/v1alpha1 这个路径的所有请求转发到后端的扩展 APIServer 中的呢?我们注意到上面的 APIService 定义中,还有一个 spec.service 字段,就是在这里,我们指定了扩展 APIServer 的服务名,也就是说 kube-apiserver 会将 /apis/wardle.example.com/v1alpha1 这个路径的所有访问通过 API 聚合层转发到后端的服务 myapi.wardle.svc 上。

Job

spec.ttlSecondsAfterFinished: 100该Job在运行结束100秒之后就被自动清理删除了,包括创建出来的Pod spec.successfulJobsHistoryLimitspec.failedJobsHistoryLimit来限制保留已完成的 Job 数量