云原生

五 Kubernetes基本概念

2022-04-28  本文已影响0人  負笈在线

(一) 为什么要用Kubernetes

1.使用裸Docker部署一些无状态的应用,随着越来越多的Docker实例,发生故障时,人工填坑的方式,让运维人员实在头疼

2.对于开发人员
  由于公司业务多,开发环境、测试环境、预生产环境和生产环境都是隔离的,而且除了生产环境,为了节省成本,其他环境是没有日志收集的,在没有用k8s的时候,查看线下测试的日志,需要开发或者测试人员,找到对应的机器,在找到对应的容器,然后才能查看日志,在用了k8s之后,开发和测试可以直接在k8s的dashboard到对应的namespace,即可定位到业务的容器,然后可以直接通过控制台查看到对应的日志,大大降低了操作时间。
  把应用部署到k8s之后,代码的发布、回滚,以及蓝绿发布、金丝雀发布等都变得特别简单,不仅加快了业务代码迭代的速度,而且全程无需人工干预。目前我们使用jenkins、gitrunner进行发版或者回滚等,从开发环境到测试环境,到最后的生产环境,完全遵守一次构建,多集群、多环境部署,通过不同的启动参数、不同的环境变量、不同的配置文件实现区分不同的环境。目前已经实现Python、Java、PHP、NodeJS、Go、.NET Core等多种语言的一键式发版、一键式回滚,大大提高了开发人员的开发效率。
  在使用服务网格后,开发人员在开发应用的过程中,不用再关心代码的网络部分,这些功能都被服务网格实现,让开发人员可以只关心代码逻辑部分,即可实现网络部分的功能,比如:断流、分流、路由、负载均衡、限速和触发故障等功能。
  测试过程中,可能同时多套环境,当然也会需要再创建一套测试环境,之前测试环境的创建,需要找运维或者自行手工搭建。在迁移至k8s集群后,只需要在jenkins上点点鼠标即可在k8s集群上创建一套新的测试环境。

3.对于运维人员
  如果你是一名运维人员,可能经常因为一些重复、繁琐的工作感觉厌倦。比如:这个需要一套新的测试环境,那个需要一套新的测试环境,之前可能需要装系统、装依赖环境、开通权限等等。而如今,可以直接用镜像直接部署一套新的测试环境,甚至全程无需自己干预,开发人员通过jenkins或者自动化运维平台即可一键式创建,大大降低了运维成本。
  一开始,公司业务故障,可能是因为基础环境不一致、依赖不一致、端口冲突等等问题,现在实现镜像部署,所有的依赖、基础都是一样的,大大减少了因为这类基础问题引发的故障。也有可能公司业务是由于服务器宕机、网络等问题,造成服务不可用,此类情况均需要运维人员及时去修复,而如今,可能在你收到告警信息的时候,k8s已经帮你恢复了。
  在没有使用k8s时,业务应用的扩容和缩容,都需要人工去处理,从采购服务器、上架、到部署依赖环境,不仅需要大量的人力物力,而且非常容易在中间过程出现问题,又要花费大量的时间去查找问题。成功上架后,还需要在前端反代端添加或该服务器,而如今,可以利用k8s的弹性计算,一键式进行扩容和缩容,不仅大大提高了运维效率,而且还节省了不少的服务器资源,提高了资源利用率。
  对于反代配置方面,比如可能你并不会,或者对nginx的配置规则并不熟悉,一些高级的功能你也不会实现,而如今,利用k8s的ingress即可简单的实现那些负责的逻辑。并且也不会在遇到nginx少加一个斜杠和多加一个斜杠的问题。
  对于负载均衡方面,之前负载均衡可能是Nginx、LVS、HAProxy、F5等,云上可能是云服务商提供的不在均衡机制。每次添加删除节点时,都需要手动去配置前端负载均衡,手动去匹配后端节点,而如今,使用k8s内部的service可以动态发现实现自动管理节点,并且支持自动扩容缩容。之前遇到高峰流量时,经常服务器性能不够,需要临时加服务器面对高峰流量,而如今对于高性能k8s集群,无需管理,自动扩容。
  对于高可用方面,k8s天生的高可用功能,彻底释放了双手,无需再去创建各类高可用工具、检测检查脚本。k8s支持进程级别的健康检查,如发现接口超时或者返回值不正确,会自动处理该问题。
  对于中间件搭建方面,根据定义好的deploy文件,可以实现秒级搭建各类中间件高可用集群,如Redis、RabbitMQ、Zookeeper等,并且大大减少了出错的概率。
  对于应用端口方面,传统行业中,一个服务器可能跑了很多进程,每个进程都有一个端口,需要人为的去配置端口,并且还需要考虑端口冲突的问题,如果有防火墙的话,还需要配置防火墙,在k8s中,端口统一管理,统一配置,每个应用的端口都可设置成一样的,之后通过service进行负载均衡。

4.无论是对于开发人员、测试人员还是运维人员,k8s的诞生,不仅减少了工作的复杂性,还减少了各种成本。上述带来的变革只是其中比较小的一部分,更多优点只有用了才能体会到。

5.Kubernetes是谷歌以Bog为前身,基于google15年生产环境经验的基础上开源的一个项目。Kubernetes致力于提供跨主机集群的自动部署、扩容、高可用以及运行应用程序容器的平台。

(二) Master节点:整个集群的控制中枢

  1. Kube-APIServer:集群的控制中枢,各个模块之间信息交互都需要经过Kube-APIServer,同时它也是集群管理、资源配置、整个集群安全机制的入口。

  2. Controller-Manager:集群的状态管理器,保证Pod或其他资源达到期望值,也是需要和APIServer进行通信,在需要的时候创建、更新或删除它所管理的资源。

  3. Scheduler:集群的调度中心,它会根据指定的一系列条件,选择一个或一批最佳的节点,然后部署我们的Pod。

  4. Etcd:键值数据库,报错一些集群的信息,一般生产环境中建议部署三个以上节点(奇数个)。

(三) Node:工作节点

  1. Kubelet:负责监听节点上Pod的状态,同时负责上报节点和节点上面Pod的状态,负责与Master节点通信,并管理节点上面的Pod。

2.Kube-proxy:负责Pod之间的通信和负载均衡,将指定的流量分发到后端正确的机器上。后面可能被eBPF取代。

查看Kube-proxy工作模式:# curl 127.0.0.1:10249/proxyMode
A.Ipvs:监听Master节点增加和删除service以及endpoint的消息,调用Netlink接口创建相应的IPVS规则。通过IPVS规则,将流量转发至相应的Pod上。
B.Iptables:监听Master节点增加和删除service以及endpoint的消息,对于每一个Service,他都会产生一个iptables规则,将service的clusterIP代理到后端对应的Pod。

其他组件
1.Calico:符合CNI标准的网络插件,给每个Pod生成一个唯一的IP地址,并且把每个节点当做一个路由器。后面可能被Cilium取代

2.CoreDNS:用于Kubernetes集群内部Service的解析,可以让Pod把Service名称解析成IP地址,然后通过Service的IP地址进行连接

3.Docker:容器引擎,负责对容器的管理。

(四) POD

1.什么是Pod?
Pod是Kubernetes中最小的单元,它有一组、一个或者多个容器组成,每个Pod还包含了一个Pause容器,Pause容器是Pod的父容器,主要负责僵尸进程的回收管理,通过Pause可以使同一个Pod里面的多个容器共享存储、网络、PID、IPC等。

Pod
2.为什么要引入Pod?
将有强依赖性的容器放在同一个Pod里,例如要求低延迟性,容器A与容器B之间文件上的联系等,引入Pod的概念是可以提高性能、便于管理。 从k8s角度说,docker是容器,但是容器却不只是docker,引入pod可以使容器间工作更协调。

3.定义一个Pod

# kubectl create deployment nginx --image=nginx -o yaml --dry-run=client >nginx.yaml
————————————————
apiVersion: v1 # 必选,API的版本号
kind: Pod       # 必选,类型Pod
metadata:       # 必选,元数据
  name: nginx   # 必选,符合RFC 1035规范的Pod名称
  # namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace 
  labels:       # 可选,标签选择器,一般用于过滤和区分Pod
    app: nginx
    role: frontend # 可以写多个
  annotations:  # 可选,注释列表,可以写多个
    app: nginx
spec:   # 必选,用于定义容器的详细信息
#  initContainers: # 初始化容器,在容器启动之前执行的一些初始化操作
#  - command:
#    - sh
#    - -c
#    - echo "I am InitContainer for init some configuration"
#    image: busybox
#    imagePullPolicy: IfNotPresent
#    name: init-container
  containers:   # 必选,容器列表
  - name: nginx # 必选,符合RFC 1035规范的容器名称
    image: nginx:1.15.2    # 必选,容器所用的镜像的地址
    imagePullPolicy: IfNotPresent     # 可选,镜像拉取策略, IfNotPresent: 如果宿主机有这个镜像,那就不需要拉取了. Always: 总是拉取, Never: 不管是否存储都不拉去
    command: # 可选,容器启动执行的命令 ENTRYPOINT, arg --> cmd
    - nginx 
    - -g
    - "daemon off;"
    workingDir: /usr/share/nginx/html       # 可选,容器的工作目录
#    volumeMounts:   # 可选,存储卷配置,可以配置多个
#    - name: webroot # 存储卷名称
#      mountPath: /usr/share/nginx/html # 挂载目录
#      readOnly: true        # 只读
    ports:  # 可选,容器需要暴露的端口号列表
    - name: http    # 端口名称
      containerPort: 80     # 端口号
      protocol: TCP # 端口协议,默认TCP
    env:    # 可选,环境变量配置列表
    - name: TZ      # 变量名
      value: Asia/Shanghai # 变量的值
    - name: LANG
      value: en_US.utf8
#    resources:      # 可选,资源限制和资源请求限制
#      limits:       # 最大限制设置
#        cpu: 1000m
#        memory: 1024Mi
#      requests:     # 启动所需的资源
#        cpu: 100m
#        memory: 512Mi
#    startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。
#      httpGet:      # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
#            path: /api/successStart # 检查路径
#            port: 80
#    readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
#      httpGet:      # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
#            path: / # 检查路径
#            port: 80        # 监控端口
#    livenessProbe:  # 可选,健康检查
      #exec:        # 执行容器命令检测方式
            #command: 
            #- cat
            #- /health
    #httpGet:       # httpGet检测方式
    #   path: /_health # 检查路径
    #   port: 8080
    #   httpHeaders: # 检查的请求头
    #   - name: end-user
    #     value: Jason 
#      tcpSocket:    # 端口检测方式
#            port: 80
#      initialDelaySeconds: 60       # 初始化时间
#      timeoutSeconds: 2     # 超时时间
#      periodSeconds: 5      # 检测间隔
#      successThreshold: 1 # 检查成功为2次表示就绪
#      failureThreshold: 2 # 检测失败1次表示未就绪
#    lifecycle:
#      postStart: # 容器创建完成后执行的指令, 可以是exec httpGet TCPSocket
#        exec:
#          command:
#          - sh
#          - -c
#          - 'mkdir /data/ '
#      preStop:
#        httpGet:      
#              path: /
#              port: 80
      #  exec:
      #    command:
      #    - sh
      #    - -c
      #    - sleep 9
  restartPolicy: Always   # 可选,默认为Always,容器故障或者没有启动成功,那就自动该容器,Onfailure: 容器以不为0的状态终止,自动重启该容器, Never:无论何种状态,都不会重启
  #nodeSelector: # 可选,指定Node节点
  #      region: subnet7
#  imagePullSecrets:     # 可选,拉取镜像使用的secret,可以配置多个
#  - name: default-dockercfg-86258
#  hostNetwork: false    # 可选,是否为主机模式,如是,会占用主机端口
#  volumes:      # 共享存储卷列表
#  - name: webroot # 名称,与上述对应
#    emptyDir: {}    # 挂载目录
#        hostPath:              # 挂载本机目录
#          path: /etc/hosts
————————————————
    apiserver:定义API的版本号
    kind:创建资源类型,如pod、deployment等
    metadata:元数据,如pod的一些基本信息
    spec:用于定义容器的详细信息

执行yaml文件创建Pod:
# kubectl create -f pod.yaml
完成后查看Pod:
# kubectl get pod
注意:生产中基本不会直接使用pod进行部署,但是yaml文件大同小异。需要熟悉yaml文件的格式和配置项。

(五) 零宕机发布应用必备知识:**

1.Pod三种探针

StartupProbe:1.16版本后增加的探针方式,用于判断容器内应用程序是否已经启动,如果配置了StartupProbe,就会先禁止其他探测,直到成功,成功后将不再进程探测。

LivenessProbe****:用于探测容器是否运行,如果探测失败,kubelet会根据配置的重启策略进行相应的处理。若没有配置该探针,默认就是success。

ReadinessProbe****:一般用于探测容器内的程序是否健康,它的返回值如果为success,那么代表这个容器已经启动成功,并且程序已经是可以接受流量的状态。

2.Pod探针检测方式:

以上探针均可配置以下方式:
ExecAction****:在容器内执行一个命令,如果返回值为0,则认为容器健康(类似于执行一个命令后,执行echo $?返回值为0代表成功是一样的)

livenessProbe:
  exec:
    command:
    - cat
    - /tmp/health

TCPSocketAction****:通过TCP连接检查容器内的端口是否通的,如果是通的则认为容器健康(类似于telnet 127.0.0.1 3306,执行成功的话判断为容器健康)

livenessProbe:
  tcpSocket:
    port: 80

HTTPGetAction****:通过应用程序暴露的API地址来检查程序是否正常,如果状态码为200~400之间,则认为容器健康。(生产使用最多)

livenessProbe:
 httpGet:
 path: /status/health
 port: 80

3.探针检查的几个参数:

initialDelaySeconds:初始化时间(比如程序启动慢,我要多少秒后才会检查)
timeoutSeconds:超时时间(1-2秒)
periodSeconds:检测间隔,多长时间检测一次(5秒)
successThreshold:检测成功次数,比如检测成功几次代表就绪(1-2次)
failureThreshold:检测失败次数,比如检测失败几次代表未就绪(2次)
重启策略:timeoutSecondsperiodSecondsfailureThreshold

以下coredns的探针配置:

# 查看pod名称
[root@k8s-master01 ~]# kubectl get deployment -n kube-system
coredns                   1/1     1            1           5d18h

# 在线编译coredns的yaml文件
[root@k8s-master01 ~]# kubectl edit deployment coredns -n kube-system
        livenessProbe:
          failureThreshold: 5
          httpGet:
            path: /health
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60           
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 5        
# 上面代表请求8080的/health接口,如果访问成功则保留容器不会被杀死
        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /ready
            port: 8181
            scheme: HTTP
          periodSeconds: 10
          successThreshold: 1
          timeoutSeconds: 1         
# 上面配置代表请求8181的/ready接口成功,说明容器可以正常开始工作了

4.Pod退出流程

Pod退出流程

5.PreStop的使用

Prestop:先去请求eureka接口,把自己的IP地址和端口号,进行下线,eureka从注册表中该应用的IP地址。然后容器进行sleep 90,kill ‘进程’;(注意90不是确定值,而是根据实际情况进行变化的)

上一篇 下一篇

猜你喜欢

热点阅读