K8S

64 阅读8分钟

历史

  • 资源调度管理(mesos被Twitter弃用;docker-swarm功能使用复杂)
  • Kubernetes Google 10年容器化基础架构 由borg系统改用go语言开发后贡献给了Apache

特点:轻量级(消耗资源小),开源、弹性伸缩、负载均衡(支持IPVS)

  • ……

原理

总体架构图

控制调度图

K8S组件说明

  • etcd可依赖的分布式kv存储服务(go语言)
    • WAL预写日志+快照:解决增量日志过大问题
  • APIServer:所有服务访问的统一入口
  • ControllerManager:维持副本期望数目
  • Scheduler:负责高度任务,选择合适的节点进行分配任务
  • Kubelet:直接跟容器引擎交互实现容器的生命周期管理
  • Kube-proxy:负责写入IPTables、LVS实现服务映射访问
  • 插件
    • CoreDNS:可以为集群中的service创建域名IP的对应关系解析
    • Dashboard:给k8s提供B/S 架构访问体系
    • Ingress Controller:Service提供的IPTables、LVS都是四层代理,而ingress提供七层代理。流量会先经过这个代理,再转到对应的Service上。
    • Federation提供跨集群中心多k8s统一管理
    • Prometheus:
    • ELK:提供K8S集群日志统一分析接入

概念

Pod

  • 类型:自主式、控制器管理式
  • 同一个Pod中的多个容器共享网络(ip是一样的)和存储卷(统一访问Pod中的pause容器) RC & RSet & Deployment
  • ReplicationController维持副本数(回收出错的Pod,新增缺少的Pod)
  • RSet与RC基本相同,多了支持集合式标签的selector(支持同一个标签多个值)
  • Deployment支持自动管理Rset(例如rolling-update) HPA(仅适用于Deployment+RSet) StatefulSet(有状态服务) DaemonSet确保全部Node上运行1个Pod副本(污点除外)
  • 运行集群存储
  • 部署每个Node上的日志收集agent、监控 Job,CronJob(保证批处理任务成功执行) 网络通讯模式
  • K8S假定所有Pod都可以直接连通的扁平空间(在GCE里自动集成了),但在私有云里就不能做这个假定,需要用其他组件实现(例如Flannel)
  • 同一个Pod里的容器:直接
  • 各Pod之间通讯:Overlay Network
  • Pod与service之间通讯:IPTables或LVS
  • Flannel之etcd(etcd存储管理Flannel可分配的IP
  • 地址段;Flannel监控etcd中每个Pod的实际地址,并在内存中维护Pod节点跌幅表

资源清单

Pod生命周期 注意与下面配置文件中的关键配置对应:initContainers、postStart、preStop、readinessProbe、livenessProbe

创建Deployment

apiVersion: apps/v1  # 指定api版本,此值必须在kubectl api-versions中  
kind: Deployment  # 指定创建资源的角色/类型   
metadata:  # 资源的元数据/属性 
  name: demo  # 资源的名字,在同一个namespace中必须唯一
  namespace: default # 部署在哪个namespace中
  labels:  # 设定资源的标签
    app: demo
    version: stable
spec: # 资源规范字段
  replicas: 1 # 声明副本数目
  revisionHistoryLimit: 3 # 保留历史版本
  selector: # 选择器
    matchLabels: # 匹配标签
      app: demo
      version: stable
  strategy: # 策略
    rollingUpdate: # 滚动更新
      maxSurge: 30% # 最大额外可以存在的副本数,可以为百分比,也可以为整数
      maxUnavailable: 30% # 示在更新过程中能够进入不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
    type: RollingUpdate # 滚动更新策略
  template: # 模版
    metadata: # 资源的元数据/属性 
      annotations: # 自定义注解列表
        sidecar.istio.io/inject: "false" # 自定义注解名字
      labels: # 设定资源的标签
        app: demo
        version: stable
    spec: # 资源规范字段
      containers:
      - name: demo # 容器的名字   
        image: demo:v1 # 容器使用的镜像地址   
        imagePullPolicy: IfNotPresent # 每次Pod启动拉取镜像策略,三个选择 Always、Never、IfNotPresent
                                      # Always,每次都检查;Never,每次都不检查(不管本地是否有);IfNotPresent,如果本地有就不检查,如果没有就拉取(手动测试时,
                                      # 已经打好镜像存在docker容器中时,使用存在不检查级别,
                                      # 默认为每次都检查,然后会进行拉取新镜像,因镜像仓库不存在,导致部署失败)
        resources: # 资源管理
          limits: # 最大使用
            cpu: 300m # CPU,1核心 = 1000m
            memory: 500Mi # 内存,1G = 1000Mi
          requests:  # 容器运行时,最低资源需求,也就是说最少需要多少资源容器才能正常运行
            cpu: 100m
            memory: 100Mi
        livenessProbe: # pod 内部健康检查的设置
          httpGet: # 通过httpget检查健康,返回200-399之间,则认为容器正常
            path: /healthCheck # URI地址
            port: 8080 # 端口
            scheme: HTTP # 协议
            # host: 127.0.0.1 # 主机地址
          initialDelaySeconds: 30 # 表明第一次检测在容器启动后多长时间后开始
          timeoutSeconds: 5 # 检测的超时时间
          periodSeconds: 30 # 检查间隔时间
          successThreshold: 1 # 成功门槛
          failureThreshold: 5 # 失败门槛,连接失败5次,pod杀掉,重启一个新的pod
        readinessProbe: # Pod 准备服务健康检查设置
          httpGet:
            path: /healthCheck
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
          periodSeconds: 10
          successThreshold: 1
          failureThreshold: 5
      	#也可以用这种方法   
      	#exec: 执行命令的方法进行监测,如果其退出码不为0,则认为容器正常   
      	#  command:   
      	#    - cat   
      	#    - /tmp/health   
      	#也可以用这种方法   
      	#tcpSocket: # 通过tcpSocket检查健康  
      	#  port: number 
        ports:
          - name: http # 名称
            containerPort: 8080 # 容器开发对外的端口 
            protocol: TCP # 协议
      imagePullSecrets: # 镜像仓库拉取密钥
        - name: harbor-certification
      affinity: # 亲和性调试
        nodeAffinity: # 节点亲和力
          requiredDuringSchedulingIgnoredDuringExecution: # pod 必须部署到满足条件的节点上
            nodeSelectorTerms: # 节点满足任何一个条件就可以
            - matchExpressions: # 有多个选项,则只有同时满足这些逻辑选项的节点才能运行 pod
              - key: beta.kubernetes.io/arch
                operator: In
                values:
                - amd64

创建Pod

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;'] # 直到myservice服务启动后,再启动本容器
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
    lifecycle:
        postStart:
          excute:
            command: ['sh', '-c', 'echo Hello!']
        preStop:
          excute:
            command: ['sh', '-c', 'echo Byebye!']
    readinessProbe:
      httpGet:
        path: /readiness
        port: 8888
      initialDelaySeconds: 300
      periodSeconds: 30
    livenessProbe:
      httpGet:
        path: /readiness
        port: 8888
      initialDelaySeconds: 300
      periodSeconds: 30

创建Service

apiVersion: v1 # 指定api版本,此值必须在kubectl api-versions中 
kind: Service # 指定创建资源的角色/类型 
metadata: # 资源的元数据/属性
  name: demo # 资源的名字,在同一个namespace中必须唯一
  namespace: default # 部署在哪个namespace中
  labels: # 设定资源的标签
    app: demo
spec: # 资源规范字段
  type: ClusterIP # ClusterIP 类型
  ports:
    - port: 8080 # service 端口
      targetPort: http # 容器暴露的端口
      protocol: TCP # 协议
      name: http # 端口名称
  selector: # 选择器
    app: demo

服务发现

服务类型:

  • ClusterIP
    • Headless Services(无头服务) 有时不需要或不想要负载均衡,以及单独的 Service IP。遇到这种情况,可以通过指定 Cluster IP(spec.clusterIP)的值为 "None" 来创建 Headless Service。 可以使用 headless Service 与其他服务发现机制进行接口,而不必与 Kubernetes 的实现捆绑在一起。
  • NodePort(在上一个基础上增加了外部访问端口)
  • LoadBalance(在上一个基础上增加了供应商负载均衡)
  • ExternalName(外部服务名,相当于CName)

网络

  • K8S v1.1 新增了iptables
  • K8S v1.8-beta 新增了ipvs
    • ipvs性能高的两个主要原因:1、ipvs工作在内核态,基于内核转发包效率高;2、LVS服务转发给RealServer时使用的二层(链路层)转发(即mac地址,同一网段)3、DR模式不需要修改三层(网络层)的信息(IP)4、DR模式和TUN模式的响应数据包不经过LVS服务;
  • K8S v1.1 新增了Ingress七层代理(其中一种插件是通过Ngnix实现的) image.png
  • 为什么从来没有使用过round robin DNS技术?客户端会缓存,更新不及时。

调度器

原则:资源公平、资源高效利用、高度效率、配置灵活 过程:1、predicate过滤不满足条件的节点 2、priority节点优先级排序,选择最高优先级节点

调度策略

predicate:

  • PodFitsResources:
  • PodFitsHost:
  • PodFitsHostPorts:
  • PodSelectorMatches:
  • NoDiskConflict
  • ……

priorigy:

  • LeastRequestedPriority:cpu和内存使用率低
  • BalancedResourceAllocation:cpu和内存使用率越接近(利用率高)
  • ImageLocalityPriority:节点本身已经有下载的镜像了,镜像越大,权重越高
  • ……

新和性

类型1:

  • 硬策略
  • 软策略

类型2:

  • NodeAffinity:以Node维度判断是否在同一位置
  • PodAffinity:以toplogyKey为维度判断是否在同一位置

污点Taint和容忍Toleration

Taint与Affinity相反,格式:key=value:effect,value可以为空,effect表示污点策略,有3种:

  • NoSchedule(不调度key=value的Pod)
  • PreferNoSchedule(尽量避免调度)
  • NoExecute(在NoSchedule的基础上,还会将已经部署的Pod驱逐。用于更新前先驱逐)

pod.spec.toleration 当不指定key时表示容忍所有污点,当不指定effact时表示容忍所有污点策略 tolerationSeconds表示Pod需要被驱逐时可以在Node上保留运行的时间

固定节点

1、 pod.spec.nodeName 指定节点名称,跳过Scheduler 1、 pod.sepc.nodeSelector 通过label-selector选择匹配label的节点

集群安全机制

认证

鉴权

RBAC: 基于角色的访问控制,K8S 1.5后默认使用的授权方式

  • 对集群中的资源和非资源均拥有完全的覆盖
  • 整个RBAC完全由几个API对象完成
  • 可以在运行时进行调整,无需重启API Server

准入控制

HELM

安装打包工具