目录
  1. 1. 基本概念
    1. 1.0.1. Kubernetes创建Pod流程
    2. 1.0.2. Kubernetes创建Service流程
  • 2. Kubernetes核心原理
    1. 2.1. kube-apiserver
    2. 2.2. kube-controller-manager原理
      1. 2.2.1. Replication Controller
      2. 2.2.2. Node Controller
      3. 2.2.3. ResourceQuota Controller
      4. 2.2.4. Namespace Controller
      5. 2.2.5. Service Controller & Endpoint Controller
      6. 2.2.6. kube-scheduler
      7. 2.2.7. kubelet
      8. 2.2.8. 网络原理
  •   《Kubernetes权威指南》的阅读笔记,由于Kubernetes项目还在快速发展中,书里有些内容已有更新的变化,不过核心内容变化不大,书还是值得认真看的。

    基本概念

    • Master
       Master是整个Kubernetes系统的调度中心,其主要由以下3个重要组件组成(原本为4个组件,但etcd存在单点此处就使用了自建的外部etcd集群):

      • kube-apiserver
         以RESTful方式提供API给外部调用,将核心对象存储在etcd中并提供增删改查功能。
      • kube-scheduler
         负责集群资源调度。监听etcd集群pod目录变化,将新增的pod按照分配算法分配到node节点中,调用kube-apiserver接口将node和pod进行关联。
      • kube-controller-manager
         Master的主要功能集中在kube-controller-manager组件上。主要负责执行不同的控制器,主要的控制器有以下几种:
        1. Endpoint Controller:维护Service和Pod的关联关系。
        2. Replication Controller:维护Pod实例的运行个数,确保Pod的运行个数和设置的一致,Pod副本数过多则销毁,过少则增加。
        3. Namespace Controller:通过调用kube-apiserver提供的接口获取Namespace信息,删除被标记为Terminating的Namespace并删除该Namespace下ServiceAccount、RC、Pod、Secret、ResourceQuota等资源。
        4. ServiceAccount Controller & Token Controller:主要负责新的Namespace中默认帐号、密钥、证书和Token的管理。
        5. Node Controller:负责发现、管理和监控Node节点。Node Controller通过定期调用kube-apiserver提供的接口获取Node节点信息(kubelet启动时调用kube-apiserver接口注册Node信息并定时更新Node信息)
        6. ResourceQuota Controller:负责资源配额控制,确保指定对象使用的系统资源在规定范围内。
        7. Service Controller:负责监控Service变化,确保外部 LoadBalancer 被更新。
    • Node
       Node是Kubernetes相对于Master的节点,Node上主要运行着众多Pod(默认Master不运行Pods等)。Node上由2个组件组成:

      • kubelet
         kubelet主要负责监控和管理Pod(启动/停止)、Volume等,定期调用kube-apiserver接口从etcd获取分配到该Node的Pod信息并启动/停止容器,定期通过kub-apiserver汇报Pod状态。
      • kube-proxy
         kube-proxy主要用于Kubernetes的Service。kube-proxy从etcd中获取Service和Endpoints(Pod’s IP+Port)信息,Kubernetes为每个Service分配一个ClusterIP,kube-proxy根据从etcd获取到的信息为每个Service随机监听一个端口,所有到该Service的请求(ClusterIP:Port)会被转发到该kube-proxy的随机端口上(通过iptables的nat实现转发),再由kube-proxy根据从etcd中获取到的信息转发给Pod(Pod在别的Node就转发到kube-proxy)。
    • Pod
       Pod是Kubernetes中最小的操作单元,一个Pod中可以有一个或多个容器(Container)(一个Pod中的多个容器应该是紧耦合的)。Pod的生命周期是通过Replication Controller来管理的,Pod被分配到具体的Node上并被创建、启动和销毁(默认Master不运行Pod )。
       Kubernetes之所以要在容器(Container)之上再封装一层Pod,是因为Docker容器之间通信麻烦和效率不高,所以通过Pod将多个紧耦合的容器(Container)组合起来,每个Pod内都会启动一个google_containers/pause的容器(Container),然后再启动所需的业务容器,业务容器通过google_containers/pause容器共享网络。
       同一个Pod内的容器共享以下资源:

      • PID Namespace:同一个Pod内的应用程序能看到其他应用程序的PID(原本不同容器的PID是相互隔离的)
      • Network Namespace:Pod内多个容器能访问同一个IP和端口(原本不同容器网络访问需要通过容器IP+Port方式,共享后同一个Pod内的所有容器都可直接通过localhost相互访问)
      • IPC Namespace:Pod内多个容器可使用SystemV IPC或POSIX消息队列通信
      • UTS Namespace:Pod内的多个容器共享一个主机名
      • Volume(共享存储卷):Pod内的多个容器可访问Pod级别的Volumes,即多个容器可共享存储空间。
    • Label
       Label以key/value的形式附加到Pod、Service、RC(ReplicationController)、Node等对象上,定义对象的可识别属性,然后通过Label Selector(选择器)对对象进行选择和管理。Replication Controller就是通过Label Selector来选择需要管理的Pod的。
       Label Selector的定义由多个逗号分隔,如下例子所示:

      1
      2
      3
      4
      "label": {
      "key1": "value1",
      "key2": "value2"
      }

       Label Selector有基于等式(Equality-based)和基于集合(Set-based)两种形式。

      • 基于等式:name = nginx,选择所有Label中key=namevalue=nginx的对象。
      • 基于集合:name in (nginx, tengine),选择所有Label中key=namevalue=nginxvalue=tengine的对象。
    • RC(Replication Controller)
       Replication Controller用于定义Pod副本的数量。Kubernetes通过Replication Controller实现动态伸缩以达到应用集群高可用的目的。
       Kubernetes可通过kubectl scale实现动态伸缩Pod

      1
      kubectl scale rc <ReplicationControllerName> --replicas=3

      删除RC,通过RC创建的Pods并不会随之跟着删除。

    • Service
       Service是一组相同服务Pod集群的对外访问入口,Kubernetes会为Service分配一个ClusterIP作为该Service的入口。引入Service是为了外部对后端Pod的变化无感知。
       Kubernetes会根据Service定义中的Label Selector,将Service和Endpoint对象(Pod的IP:Port)关联起来。查看Endpoint对象:

      1
      kubectl get endpoints

       Kubernetes分配给Service的ClusterIP只能在内部访问,若想Service被外部访问则需要分配一个”公网IP”。暴露Service的方式有三种:

      • NodePort:这种是最常用的方式,直接在Node机器上监听端口。在定义Service时指定spec.type=NodePort并指定spec.ports.nodePort的值。Kubernetes会在Node上监听spec.ports.nodePort端口提供外部访问。并非一定要要指定spec.ports.nodePort的值,spec.ports.nodePort端口的范围必须在30000~32767内,不指定spec.ports.nodePort则会随机在范围内分配一个IP。
      • LoadBalancer:这种是在云服务(GCE/AWS)提供LoadBalancer时可使用,在定义Service时指定spec.type=LoadBalancer并指定Service的nodePortClusterIP
      • Ingress:Ingress是Kubernetes1.2版本后引入的,通过Ingress来利用Nginx/HAProxy等常见开源反向代理软件实现对外暴露服务功能。
    • Volume
       Volume是Pod中能被多个容器访问的共享目录。Kubernetes的Volume和Docker的Volume差不多,但Kubernetes的Volume是随Pod销毁而销毁的,Pod中的容器停止或重启不影响Kubernetes的Volume。
       Kubernetes提供多种类型的Volume,如下所示:

      • EmptyDir:EmptyDir Volume在Pod被分配到Node时创建,Pod内的所有容器都可以读写EmptyDir中的文件。Pod被删除时EmptyDir也会被删除。
      • hostPath:hostPath Volume是在Pod中挂载宿主机上的文件或目录。常用于需要持久保留的文件。由于Pod可能分配到多个Node上,挂载多个Node的hostPath Volume可能会导致数据的不一致。可在创建RC的时候指定Pod挂载宿主机的目录,比如将宿主机中/data目录挂载到Pod容器内的/data上:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        apiVersion: v1
        kind: ReplicationController
        metadata:
        name: nginx
        labels:
        name: nginx
        spec:
        replicas: 2
        selector:
        name: nginx
        template:
        metadata:
        labels:
        name: nginx
        spec:
        volumes:
        - name: "nginx-log"
        hostPath:
        path: "/data"
        containers:
        - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        volumeMounts:
        - name: "nginx-log"
        mountPath: "/data"
      • gcePersistentDisk:使用GCE的永久磁盘(Persistent Disk),当Pod被删除时,这类磁盘只被卸载不会被删除。

      • awsElasticBlockStore:使用AWS的EBS。
      • nfs:使用NFS提供的目录挂载到Pod中。
      • glusterfs:使用GlusterFS提供的目录挂载到Pod中。
      • rdb:使用Linux块设备共享存储挂载到Pod中。
      • gitRepo:通过挂载一个空目录,并从GIT库clone一个git repository以供pod使用。
      • secret:为Pod提供加密存储,Secret Volume是通过tmpfs实现的,不能持久化。
      • persistentVolumeClaim:从PV(persistentVolume)中申请所需的空间,PV通常是种网络存储,如GCEPersistentDisk、AWSElasticBlockStore、NFS、iSCSI等。
    • Namespace
       Kubernetes的Namespace和Linux系统中的Namespace并非同一个东西,但功能相似都是用于隔离。Kubernetes通过将对象分配到不同的Namespace中以达到分组管理的目的。
       Kubernetes启动后会创建一个default的Namespace,使用kubeadm部署集群的话会创建kube-system的Namespace。若不知道资源对象的Namespace,则Pod、RC、Service等都会被创建到default的默认Namespace中。可通过以下命令查看Namespace:

      1
      kubectl get namespace

       可通过yaml文件创建Namespace:

      1
      2
      3
      4
      5
      #namespace-test.yaml
      apiVersion: v1
      kind: Namespace
      metadata:
      name: test
      1
      kubectl create -f namespace-test.yaml
    • Annotation
       Annotation也是使用key/value形式进行定义,个人理解为相当于备注的作用。

    Kubernetes创建Pod流程

    1. 通过kubectl提交一个创建RC请求给kube-apiserverkube-apiserver将请求存到etcd
    2. kube-controller-manager通过调用kube-apiserver接口得知创建RC事件,分析后发现集群中没有该RC对应的Pod,根据RC定义中的Pod模板生成Pod对象并调用kube-apiserver接口存入etcd
    3. kube-scheduler监听etcd发现有创建Pod事件,kube-scheduler根据算法得出Pod被分配到哪个Node,调用kube-apiserver将结果存入etcd
    4. 目标Node上的kubectl通过调用kube-apiserver得知需要创建Pod并按照相关定义创建Pod及容器。该Node的kubectl对Pod进行监控和管理并定期调用kube-apiserver接口上报Pod的状态。

    Kubernetes创建Service流程

    1. 通过kubectl提交创建Service请求给kube-apiserverkube-apiserver将请求存到etcd
    2. kube-controller-manager调用kube-apiserver接口得知创建Service事件,通过Label查询到与Service相关的Pod,生成Service的Endpoint信息并调用kube-apiserver接口存入etcd
    3. Node上的kube-proxy调用kube-apiserver接口查询到Service和对应Endpoint信息,在Node上监听随机端口,配置iptables将所有到Service的ClusterIP:Port的请求都转发到kube-proxy监听的随机端口上,kube-proxy将请求转发到Pod上。

    Kubernetes核心原理

    kube-apiserver

      kube-apiserver默认会监听两个端口,一个是非安全用于接受HTTP请求的8080端口,另一个是安全的HTTPS端口6443用于认证等安全机制请求,kube-apiserver主要功能:

    • 提供集群管理API接口
    • 集群各功能模块间数据交互和通信的中枢
    • 提供安全机制

      Kubernetes提供kubectl命令行工具将API功能封装成简单的命令集。更多具体功能使用kubectl -h获取。
      kube-apiserver提供API接口访问Pod、Node和Service等,详细的API接口没去研究。
      Kubernetes中基本上都是通过调用kube-apiserver提供的接口完成集群中模块间信息的交换的。比如Node上的kubectl会定期调用API报告节点状态并存入etcd中,Node Controller通过调用API获取到节点相关信息并作出相应操作。为了缓解kube-apiserver的压力各功能模块会定时调用API获取信息并保持到本地缓存,使得某些情况下模块不需要直接调用API而通过访问缓存数据间接调用API。

    kube-controller-manager原理

      kube-controller-manager作为Kubernetes集群的管理控制中心,对集群内的Node、Pod副本、Endpoint、Namespace、ServiceAccount和ResourceQuota等资源进行管理及执行自动修复流程。如上所说,kube-controller-manager是由多个Controller组成,对各个Controller进行较深入了解。

    Replication Controller

      Replication Controller的主要功能是确保Pod的副本数目和RC定义中的一致。正常来说,都是通过RC来创建Pod的,所以Replication Controller的管理对象是Pod。Pod的状态值如下:

    • pending:API Server已创建Pod,但Pod内有一个或多个容器没创建
    • running:Pod内所有容器已创建,且至少有一个容器正常运行
    • successded:Pod内所有容器均停止成功且不会再重启
    • failed:Pod内所有容器已退出,且至少一个发生错误退出

      Pod的重启策略有三种AlwaysOnFailureNever,只有是Always时,Replication Controller才会管理该Pod。当Pod副本状态为failed或被删除且RestartPolicy=Always时,Replication Controller会重新创建该Pod的副本。

      通过具体的RC实例来说明Replication Controller是如何创建Pod的。创建一个Nginx的RC实例,启动2个Pod:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    apiVersion: v1
    kind: ReplicationController
    metadata:
    name: nginx
    labels:
    name: nginx
    spec:
    replicas: 2
    selector:
    name: nginx
    template:
    metadata:
    labels:
    name: nginx
    spec:
    containers:
    - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80

    • kind: ReplicationController:指明这是个ReplicationController
    • spec.replicas:指明该RC的Pod副本数目
    • spec.selector:指明该RC关联的Pod
    • spec.template:RC创建的Pod实例都是根据RC定义中的创建。
    • spec.template.spec.containers:指明Pod中容器的属性(该使用什么镜像、端口等)

      需要注意到是,删除RC并不会影响其所已经创建的Pod。Pod可以通过修改其Label实现脱离RC的管控(RC是通过spec.selector中的name来关联Pod的)。
      Replication Controller主要就是根据RC定义中的spec.replicas值来调整Pod的副本数目,以确保集群中有且仅有spec.replicas个Pod实例。
      Replication Controller的常用模式如下:

    • Rescheduling:重新调度,即在Pod副本实例发生异常时重新创建Pod副本实例。
    • Scaling:手动或自动扩容/缩容。可通过kubectl scale命令实现

      1
      kubectl scale rc <ReplicationControllerName> --replicas=<NUM>
    • Rolling Updates:滚动更新,ReplicationController通过逐个对Pod进行更新来实现滚动升级。一般是重新创建一个RC,然后新RC中的Pod数目不断增加,旧RC中Pod数目不断减少直至0

      1
      kubectl rolling-update <OLD_RC_NAME> --update-period=10s -f <NEW_RC>.yaml

       Kubernetes1.2版本后推荐使用Deployment来进行Rolling Updates。新的Deployment会创建ReplicaSet,关于这个内容改天专门来写。

    Node Controller

      Node Controller主要负责发现、管理和监控Node。kubectl启动时调用API注册Node并定时调用API上报Node信息,kube-apiserver将Node信息存入etcd。Node信息包括:Node健康状态、节点资源、节点名称、节点地址信息、OS版本、Docker版本和kubelet版本。
      Node健康状态分为:True(就绪)、False(未就绪)和Unknown(未知)
      Node Controller会定期调用API接口获取Node信息。如果kube-controller-manager启动时没有指定CIDR则为每个Node生产CIDR并设置Node的spec.PodCIDR属性;逐个读取Node信息并和Node Controller中nodeStatusMap中保存的信息做对比,若无变化则更新探测时间,有变化则更新nodeStatusMap中的信息。若规定时间内没收到Node信息则将状态设置为Unknown并调用API存入etcd。再逐个读取Node信息,将非True状态Node加入待删队列,若发现该Node故障则删除etcd中Node信息及相关资源信息。

    ResourceQuota Controller

      ResourceQuota Controller是对Kubernetes集群进行资源配额管理的,支持三个层次的资源配额管理:

    • 容器级别:对容器CPU和Memory进行限制
    • Pod级别:对Pod内所有容器进行资源限制
    • Namespace级别:Namespace级别的限制包括以下方面:
      • Pod数量
      • RC数量
      • Service数量
      • ResourceQuota数量
      • Secret数量
      • PV(persistentVolume)数量

      Kubernetes中配额管理是通过准入机制(admission control)实现的,配额的准入控制器有LimitRangerResourceQuota,LimitRanger作用于Pod和Container,ResourceQuota作用于Namespace。
      ResourceQuota Controller以Namespace作为分组统计单元,调用API定时从etcd中获取每个Namespace中的ResourceQuota信息,计算Pod、RC、Service等资源对象和Container实例使用的资源(CPU/Memory)并调用API存入etcd。用户请求创建资源时,kube-apiserver调用admission controller的ResourceQuota插件从etcd中配额信息,若某项资源超过配额则该请求被拒绝。

    Namespace Controller

      Namespace Controller主要就是用来管理Namespace的。当Namespace被标记为优雅删除(即设置了DeletionTimestamp删除期限),则该Namespace状态被设置为Terminating。Namespace Controller会删除该Namespace下的所有资源,然后执行finalize操作(删除spec.finalizers信息)。当Namespace Controller发现一个Namespace设置了DeletionTimestampspec.finalizers值为空则调用API删除Namespace。

    Service Controller & Endpoint Controller

      当调用API创建Service时,Kubernetes会为该Service指派一个集群内网IPClusterIP,Service中的spec.selector指明该Service和name: nginx的Pod关联,每个Pod的80端口都被映射到本地节点的80端口(targetPort)。创建Service时指定了spec.selector的话,Kubernetes会创建一个和Service同名的Endpoint对象。该Endpoint对象其实就是和Service关联的Pod的IP+Port。
      也可创建没spec.selector的Service,Kubernetes便不会自动创建与之相关的Endpoint,可手动创建和Service同名的Endpoint指定后端Pod。
     创建Nginx的Service实例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    apiVersion: v1
    kind: Service
    metadata:
    name: nginx-service
    labels:
    name: nginx-service
    spec:
    ports:
    - port: 80
    targetPort: 80
    protocol: TCP
    selector:
    name: nginx

      Service是Kubernetes中的对象,请求从Service到Pod的工作是由kube-proxy来完成的。kube-proxy为每个Service在本机上随机监听一个端口,通过添加iptables规则将访问Service的请求转发到kube-proxy的随机端口,然后kube-proxy根据Round Robin算法及Session保持(SessionAffinity)决定将请求转发到后端的哪个Pod。
      Kubernetes支持两种模式找到Service:

    • Container的Service环境变量
      在创建Pod时,在所有Pod中的Container中加入一系列的Service环境变量,如{SVCNAME}_SERVICE_HOST/{SVCNAME}_SERVICE_PORT等,{SVCNAME}是大写的Service Name,若有-则自动转换为_
    • DNS
      DNS服务器通过调用API监控Service相关活动,新增Service时创建一系列DNS记录。
      更为常用的是DNS SVC被命名端口的记录,若service_name.namespace_name的Service有名为”http”的端口,则可用_http._tcp.service_name.namespace_name通过DNS服务器找到对于的Pod暴露端口。

      对于Service的暴露,如前面所说常用三种方式:LoadBalancerNodePortIngress。详细参照前面。
      Service Controller和Endpoint Controller分别监控Service和Endpoint对象,调用API更新变更再存入etcd中。

    kube-scheduler

      kube-scheduler主要负责Pod的调度,将待调度的Pod按照特定的调度算法和调度策略绑定到合适的Node上并将信息存入etcd。Node上的kubelet监听到kube-scheduler产生的Pod绑定事件后,获取对应的Pod清单、下载image镜像并启动Container容器。
      kube-scheduler默认调度流程分两步,Kubernetes提供一系列的预选策略和优选策略,此处不一一具体分析:

    • 预选策略:遍历所有Node,筛选符合条件的Node。
    • 优选策略:基于预选策略,采用优选策略计算积分,最终选出最佳Node。

    kubelet

      Kubernetes会在每个Node节点中运行kubeletkubelet主要负责以下功能:

    • Node管理
      kubelet在启动时会调用API以注册Node信息(可手动设置不进行自动注册),并定期调用API将信息存入etcd。
    • Pod管理
      kubelet通常通过以下3种获取Node上的Pod清单:
      • 文件:在启动kubelet时指定,--pod-manifest-path=/etc/kubernetes/manifests
      • HTTP URL:指定--manifest-url
      • API Server:调用API监听etcd目录同步Pod清单。
        前两种非API Server方式创建的Pod称之为Static Podkubelet会将Static Pod汇报给API Server,API Server会为Static Pod创建Mirror Pod与其匹配。
        kubelet通过API Server方式创建或修改Pod大致流程如下:
      1. 创建Pod的数据目录
      2. 调用API获取Pod清单
      3. 挂载外部卷(Extenal Volume)到Pod
      4. 下载Pod所需的Secret
      5. 检查Node运行中的Pod,若Pod中无容器或Pause容器没启动,则先停止Pod内所有容器,若有要删除的容器则删除
      6. 为每个Pod创建Pause容器,Pod中的其他容器通过Pause容器共享网络
      7. 为Pod中的每个容器做如下处理:为容器计算hash值,用容器名去Docker查询对应容器的hash值,若hash值不同则停止容器。若设置了restartPolicy则按照策略处理,无则调用Docker client下载镜像并运行容器。
    • 健康检查
      Pod通过两种探针检查容器健康状态:

      • LivenessProbe:用于判断容器是否健康。若不健康,kubelet则删除容器并按照restartPolicy策略处理。LivenessProbe检查可分成三种实现方式,LivenessProbe的定义在Pod的spec.containers中:

        1. ExecAction:容器内执行一条命令,退出码为0则健康

          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          spec:
          containers:
          - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 80
          livenessProbe:
          exec:
          command:
          - cat
          - /tmp/healthy
          initialDelaySeconds: 5
          periodSeconds: 3
        2. TCPSocketAction:对容器内端口做TCP检测,端口能被访问则健康

        3. HTTPGetAction:对容器特点的端口+路径调用GET方法,HTTP响应状态码在200~400之间为健康
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          spec:
          containers:
          - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 80
          livenessProbe:
          httpGet:
          path: /heath_pah
          port: 80
          httpHeaders:
          - name: X-Custom-Header
          value: Awesome
          initialDelaySeconds: 5
          periodSeconds: 3
      • ReadinessProbe:用于判断容器是否启动完成且准备接受请求。若ReadinessProbe检查失败,Endpoint Controller会删除Service中该Pod的Endpoint信息。

    网络原理

    • Kubernetes网络模型
        Kubernetes使用的网络模型称为IP-per-Pod模型,每个Pod拥有单独的IP地址,IP是以Pod为单位分配的。一个Pod内的所有容器共享网络(使用同一个Network Namespace通过Pause容器实现),IP和端口在Pod内部和外部都是一致的(不需要NAT)。
        Kubernetes设计之初是运行在谷歌的GCE环境上的,GCE默认就支持Kubernetes的网络。但要在非GCE环境运行Kubernetes则需要先搭建出符合Kubernetes网络要求的环境,目前开源的方案有很多诸如Flannel、Weave等用于实现Kubernetes中容器与容器之间网络的环境。
        Kubernetes主要针对一下几种网络场景制定不同的解决方案:

      • 容器间通信
        这里的容器间通信特指在同一个Pod内的容器间通信,正如前面所说,同一个Pod内的容器是通过Pause容器共享同一个Network Namespace的,同一个Pod内的容器甚至可以通过localhost直接访问彼此的端口,这就使得同一个Pod内容器间的通信变得简单高效。
      • Pod间通信

        • 同一Node中Pod间通信
          由于同一个Node中的不同Pod都是通过veth连接到同一个docker0网桥上,Pod的IP地址和docker0的IP地址在同一个网段内,所有同一个Node上的不同Pod都由docker0网桥进行中转,可直接通信。
        • 不同Node中Pod间通信
          由于Pod的IP是隐藏在docker0网桥后的,出了docker0后不同Node之间的Pod是无法感知到对方,所以需要有完善的网络方案使得Pod之间能使用私有IP进行通信、集群内Pod的IP分配不会冲突、Pod的IP和Node的IP关联(Pod通信时需要先找到Node)。为此有了多个不同的开源网络组件:

          • Flannel
            Flannel会创建flannel0网桥,一端连接docker0,另一端连接flanneld服务进程。flanneld服务进程利用etcd来管理分配IP并监听etcd中每个Pod的IP,创建Pod节点路由表。flanneld服务进程根据Pod节点路由表将从docker0发来的数据包进行封装通过物理网络传输到目的flanneld上,以此完成不同Node上的Pod通信。

            1
            containerA-->docker0-->flannel0-->flanneld-->NodeA-->[Network]-->NodeB-->flanneld-->flannel0-->docker0-->containerB
          • Open vSwitch
            Open vSwitch是一个开源虚拟交换机软件,该项目较成熟但比较复杂,一般最求高性能网络的话网上都比较推荐此方案,由于比较复杂我也没怎么研究。

          • 直接路由
            简单来说,直接路由就是让集群能够通过docker0直接通信,让每个Node的路由表有到所有docker0的路由,将docker0和Node的eth0关联起来。简单的可手动在所有Node上添加到集群内所有docker0地址的路由,但更实际的方案是结合动态路由协议来做。
      • Pod和Service间通信
        正如前面所说,Pod和Service间的通信是通过kube-proxy实现的,kube-proxy为Service随机监听一个端口并添加iptables规则将到Service的请求转发到kube-proxy,再由kube-proxy根据Endpoint信息转发到后端的Pod。
        值得一提的是如果Service定义中指定了Session保持,则kube-proxy会查看是否存在改IP的affinityState对象,存在则转到改对象对应的Pod。
      • 外部到内部访问
        同样如前面所说,外部访问内部目前主要有3种方式:NodePort、LoadBalancer和Ingress。接下来重点讲一下Ingress
        Ingress是利用Nginx/HAProxy等反向代理软件来暴露服务,从而实现外部到内部的访问,Ingress可根据URL(/serviceA)、域名来进行暴露Service。
        Ingress在Kubernetes中也是一个对象资源,Kubernetes使用Ingress Controller来对控制管理Ingress资源,Ingress Controller主要与Kubernetes API交互,负责感知规则变化,然后生成配置文件,最后reload Pod中的Nginx。Ingress Controller不像其他Controller一样包含在kube-controller-manager里,需要选择适合的Ingress Controller并运行。

    Powered: Hexo, Theme: Nadya remastered from NadyMain