• k8s - Flannel


    1.Flannel概念剖析

    Flannel是 CoreOS 团队针对 Kubernetes 设计的一个覆盖网络(Overlay Network)工具,其目的在于帮助每一个使用 Kuberentes 的 CoreOS 主机拥有一个完整的子网。这次的分享内容将从Flannel的介绍、工作原理及安装和配置三方面来介绍这个工具的使用方法。

    Flannel通过给每台宿主机分配一个子网的方式为容器提供虚拟网络,它基于Linux TUN/TAP,使用UDP封装IP包来创建Overlay网络,并借助Etcd维护网络的分配情况。Flannel is a simple and easy way to configure a layer 3 network fabric designed for Kubernetes.

    2. Flannel工作原理

    Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的IP地址。

    在默认的Docker配置中,每个Node的Docker服务会分别负责所在节点容器的IP分配。Node内部得容器之间可以相互访问,但是跨主机(Node)网络相互间是不能通信。

    Flannel设计目的就是为集群中所有节点重新规划IP地址的使用规则,从而使得不同节点上的容器能够获得"同属一个内网"并且"不重复的"IP地址,并让属于不同节点上的容器能够直接通过内网IP通信。

    Flannel 使用Etcd存储配置数据和子网分配信息。Flannel 启动之后,后台进程首先检索配置和正在使用的子网列表,然后选择一个可用的子网,然后尝试去注册它。Etcd也存储这个每个主机对应的IP。

    Flannel 使用Etcd的watch机制监视/atomic.io/network/subnets下面所有元素的变化信息,并且根据它来维护一个路由表。为了提高性能,Flannel优化了Universal TAP/TUN设备,对TUN和UDP之间的IP分片做了代理。

    3. Flannel架构介绍

    Flannel默认使用8285端口作为UDP封装报文的端口,VxLan使用8472端口。
    在这里插入图片描述
    那么一个网络报文请求是怎么从一个容器发送到另外一个容器的呢?例如从node1上的Container1容器(IP:10.244.0.13)访问node2上面Container2容器(IP:10.244.1.14)容器。

    • Container1容器10.244.0.13直接访问目标容器Container2的IP 10.244.1.14,请求默认通过容器内部的eth0网卡发送出去。
    • 请求报文通过Veth pair(虚拟设备对)被发送到Docker宿主机VethXXX设备上。
    • VethXXX设备是直接连接到虚拟交换机Docker0(Cni0)的,所以请求报文通过虚拟Bridge Docker0发送出去。
    • 然后查找Docker宿主机的路由表信息,同时外部容器IP的报文都会转发到Flannel0虚拟网卡,这是一个P2P的虚拟网卡,然后报文就被转发到监听在另一端的Flanneld进程。
    • 因为Flannel在Etcd中存储着子网和宿主机ip的对应关系,所以能够找到10.244.1.14对应的宿主机IP为11.101.1.3,进而开始组装UDP数据包发送数据到目的主机。
      这个请求得以完成的原因每个节点上都启动着一个Flanneld udp进程,都监听着8285端口,所以node1通过Flanneld进程把数据包通过宿主机的Interface网卡发送给node2的Flanneld进程的相应端口即可。
    • 请求报文到达node2之后,继续往上传输,到传输层,交给监听在8285端口的Flanneld程序处理。
    • 请求数据被解包,然后发送给Flannel0虚拟网卡。
    • 查找路由表,发现对应容器的报文要交给Docker0(cni0)。
    • Docker0找到连到自己的容器,把报文发送给Container2,反之同样的工作方式。

    4. Kubernetes工作原理剖析

    Kubernetes集群是一组节点,这些节点可以是物理服务器或者虚拟机,在其上安装Kubernetes平台。下图为了强调核心概念有所简化。Kubernetes架构图。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    从上图,我们可以看到K8S组件和逻辑关系:Kubernetes集群主要由Master和Node两类节点组成。Master的组件包括:Apiserver、Controller-manager、Scheduler和Etcd等几个组件,其中Apiserver是整个集群的网关。

    Node主要由kubelet、kube-proxy、docker引擎等组件组成。kubelet是K8S集群的工作与节点上的代理组件。

    在企业生产环境中,一个完整的K8S集群,还包括CoreDNS、Prometheus(或HeapSter)、Dashboard、Ingress Controller等几个附加组件。其中cAdivsor组件作用于各个节点(master和node节点)之上,用于收集及收集容器及节点的CPU、内存以及磁盘资源的利用率指标数据,这些统计数据由Heapster聚合后,可以通过apiserver访问。
    K8S集群中创建一个资源(Pod容器)的工作流程和步骤:

    • 客户端提交创建(Deployment、Namespace、Pod)请求,可以通过API Server的Restful API,也可以使用kubectl命令行工具。
    • 然后API Server处理用户的请求,并且存储相关的数据(Deployment、Namespace、Pod)到Etcd配置数据库中。
    • K8S Scheduler调度器通过API Server查看未绑定的Pod。尝试为该Pod分配Node主机资源。
    • 过滤主机 (调度预选):调度器用一组规则过滤掉不符合要求的主机。比如Pod指定了所需要的资源量,那么可用资源比Pod需要的资源量少的主机会被过滤掉。
    • 主机打分(调度优选):对第一步筛选出的符合要求的主机进行打分,在主机打分阶段,调度器会考虑一些整体优化策略,比如把容一个Replication Controller的副本分布到不同的主机上,使用最低负载的主机等。
    • 选择主机:选择打分最高的主机,进行binding操作,结果存储到etcd中。
    • Node节点上Kubelet根据调度结果,调用主机上的Docker引擎执行Pod创建操作,绑定成功后,Scheduler会调用APIServer的API在etcd中创建一个boundpod对象,描述在一个工作节点上绑定运行的所有pod信息。
    • 同时运行在每个工作节点上的Kubelet也会定期与etcd同步boundpod信息,一旦发现应该在该工作节点上运行的boundpod对象没有更新,则调用Docker API创建并启动pod内的容器。

    5. Kubernetes 本地私有仓库实战

    Docker仓库主要用于存放Docker镜像,Docker仓库分为公共仓库和私有仓库,基于registry可以搭建本地私有仓库,使用私有仓库的优点如下:
    节省网络带宽,针对于每个镜像不用去Docker官网仓库下载;
    下载Docker镜像从本地私有仓库中下载;
    组件公司内部私有仓库,方便各部门使用,服务器管理更加统一;
    可以基于GIT或者SVN、Jenkins更新本地Docker私有仓库镜像版本。
    官方提供Docker Registry来构建本地私有仓库,目前最新版本为v2,最新版的docker已不再支持v1,Registry v2使用Go语言编写,在性能和安全性上做了很多优化,重新设计了镜像的存储格式。如下为在192.168.1.147服务器上构建Docker本地私有仓库的方法及步骤:
    (1)下载Docker registry镜像,命令如下:

    docker pull registry
    
    • 1

    (2)启动私有仓库容器,启动命令如下:

    mkdir -p  /data/registry/
    docker run -itd  -p  5000:5000 -v /data/registry:/var/lib/registry  docker.io/registry
    
    • 1
    • 2

    Docker本地仓库启动后台容器启动,如图24-2所示:
    在这里插入图片描述
    默认情况下,会将仓库存放于容器内的/tmp/registry目录下,这样如果容器被删除,则存放于容器中的镜像也会丢失,所以我们一般情况下会指定本地一个目录挂载到容器内的/tmp/registry下。

    (3)上传镜像至本地私有仓库:
    客户端上传镜像至本地私有仓库,如下以busybox镜像为例,将busybox上传至私有仓库服务器。

    docker   pull    busybox
    docker   tag    busybox  192.168.1.147:5000/busybox
    docker   push  192.168.1.147:5000/busybox
    
    • 1
    • 2
    • 3

    (4)检测本地私有仓库:

    curl -XGET http://192.168.1.147:5000/v2/_catalog
    curl -XGET http://192.168.1.147:5000/v2/busybox/tags/list
    
    • 1
    • 2

    (5)客户端使用本地私有仓库:
    客户端docker配置文件添加如下代码,同时重启docker服务,获取本地私有仓库如图24-3所示:

    OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false --insecure-registry 192.168.1.147:5000'
    ADD_REGISTRY='--add-registry 192.168.1.147:5000'
    
    • 1
    • 2

    在这里插入图片描述
    至此,docker本地私有仓库部署完毕,可以向仓库中添加或者更新Docker镜像。
    在K8S Docker客户端主机添加本地仓库地址,添加方法如下:
    vim /etc/docker/daemon.json文件中代码如下:

    {
    "insecure-registries":["192.168.1.147:5000"]
    }
    
    • 1
    • 2
    • 3

    6. Kubernetes+Jenkins+Docker仓库整合

    在企业生产环境中,通常会将K8S+Jenkins+Docker仓库整合起来,实现业务全自动发布。需求如下:
    1)K8S云计算平台、Jenkins平台、Docker仓库平台;(提前准备好)
    2)部署一套bbs.jfedu.net业务,在Jenkins创建工程-绑定SVN仓库地址-从SVN下载网站代码;
    3)网站代码下载成功-制作CentOS7镜像-将网站程序打包至镜像中;
    4)将制作的CentOS7镜像(网站程序)-上传至Docker仓库平台;
    5)基于K8S云计算平台-部署bbs.jfedu.net业务(CentOS云主机)-NodePort端口-外网用户访问。
    6)编写SHELL编程脚本,实现以上步骤整合操作,SHELL代码如下:

    #进入Jenkins工程目录;
    cd /root/.jenkins/workspace/bbs.jfedu.net/
    #查看从SVN下载网站代码;
    ls -l index.html
    #创建Dockerfile镜像制作文件;
    cat>Dockerfile<<EOF
    #2022年11月23日11:22:12
    #指定基础镜像;
    FROM ansible/centos7-ansible:latest
    #指定维护者信息;
    MAINTAINER www.jfedu.net 2022
    #指定工作目录;
    WORKDIR /root/
    #删除EPEL扩展源;
    RUN rm -rf /etc/yum.repos.d/epel*
    #安装网络工具和openssh server服务;
    RUN yum install -y net-tools openssh-server httpd
    #修改系统密码为1;
    RUN echo 1|passwd --stdin root
    #生成SSHD服务启动基础KEY文件;
    RUN ssh-keygen -A
    #将网站程序部署至镜像中;
    COPY index.html /var/www/html/
    RUN chmod 644 /var/www/html/index.html
    #暴露映射目录;
    VOLUME /var/www/html/
    #指定容器入口命令;
    ENTRYPOINT /usr/sbin/init
    CMD /usr/sbin/sshd -D
    EOF
    #制作CentOS7镜像文件;
    docker build -t centos7-ssh:v2 ./
    #修改CentOS7镜像文件tag号;
    docker tag centos7-ssh:v2 10.0.12.13:5000/centos7-ssh:v2
    #将CentOS7镜像上传Docker私有仓库;
    docker push 10.0.12.13:5000/centos7-ssh:v2
    #创建K8S bbs-jfedu-net部署yaml文件;
    cat>bbs-jfedu-net.yaml<<EOF
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: bbs-jfedu-net
      namespace: default
      uid: 16adfc69-ecf1-48d3-9190-518ecffb8818
      resourceVersion: '3854'
      generation: 1
      creationTimestamp: '2022-11-23T13:02:03Z'
      labels:
        k8s-app: bbs-jfedu-net
      annotations:
        deployment.kubernetes.io/revision: '1'
      managedFields:
        - manager: dashboard
          operation: Update
          apiVersion: apps/v1
          time: '2022-11-23T13:02:03Z'
          fieldsType: FieldsV1
          fieldsV1:
            'f:metadata':
              'f:labels':
                .: {}
                'f:k8s-app': {}
            'f:spec':
              'f:progressDeadlineSeconds': {}
              'f:replicas': {}
              'f:revisionHistoryLimit': {}
              'f:selector': {}
              'f:strategy':
                'f:rollingUpdate':
                  .: {}
                  'f:maxSurge': {}
                  'f:maxUnavailable': {}
                'f:type': {}
              'f:template':
                'f:metadata':
                  'f:labels':
                    .: {}
                    'f:k8s-app': {}
                  'f:name': {}
                'f:spec':
                  'f:containers':
                    'k:{"name":"bbs-jfedu-net"}':
                      .: {}
                      'f:image': {}
                      'f:imagePullPolicy': {}
                      'f:name': {}
                      'f:resources': {}
                      'f:securityContext':
                        .: {}
                        'f:privileged': {}
                      'f:terminationMessagePath': {}
                      'f:terminationMessagePolicy': {}
                  'f:dnsPolicy': {}
                  'f:restartPolicy': {}
                  'f:schedulerName': {}
                  'f:securityContext': {}
                  'f:terminationGracePeriodSeconds': {}
        - manager: kube-controller-manager
          operation: Update
          apiVersion: apps/v1
          time: '2022-11-23T13:02:04Z'
          fieldsType: FieldsV1
          fieldsV1:
            'f:metadata':
              'f:annotations':
                .: {}
                'f:deployment.kubernetes.io/revision': {}
            'f:status':
              'f:conditions':
                .: {}
                'k:{"type":"Available"}':
                  .: {}
                  'f:lastTransitionTime': {}
                  'f:lastUpdateTime': {}
                  'f:message': {}
                  'f:reason': {}
                  'f:status': {}
                  'f:type': {}
                'k:{"type":"Progressing"}':
                  .: {}
                  'f:lastTransitionTime': {}
                  'f:lastUpdateTime': {}
                  'f:message': {}
                  'f:reason': {}
                  'f:status': {}
                  'f:type': {}
              'f:observedGeneration': {}
              'f:replicas': {}
              'f:unavailableReplicas': {}
              'f:updatedReplicas': {}
    spec:
      replicas: 1
      selector:
        matchLabels:
          k8s-app: bbs-jfedu-net
      template:
        metadata:
          name: bbs-jfedu-net
          creationTimestamp: null
          labels:
            k8s-app: bbs-jfedu-net
        spec:
          containers:
            - name: bbs-jfedu-net
              image: '10.0.12.13:5000/centos7-ssh:v2'
              resources: {}
              terminationMessagePath: /dev/termination-log
              terminationMessagePolicy: File
              imagePullPolicy: IfNotPresent
              securityContext:
                privileged: true
          restartPolicy: Always
          terminationGracePeriodSeconds: 30
          dnsPolicy: ClusterFirst
          securityContext: {}
          schedulerName: default-scheduler
      strategy:
        type: RollingUpdate
        rollingUpdate:
          maxUnavailable: 25%
          maxSurge: 25%
      revisionHistoryLimit: 10
      progressDeadlineSeconds: 600
    status:
      observedGeneration: 1
      replicas: 1
      updatedReplicas: 1
      unavailableReplicas: 1
      conditions:
        - type: Available
          status: 'False'
          lastUpdateTime: '2022-11-23T13:02:04Z'
          lastTransitionTime: '2022-11-23T13:02:04Z'
          reason: MinimumReplicasUnavailable
          message: Deployment does not have minimum availability.
        - type: Progressing
          status: 'True'
          lastUpdateTime: '2022-11-23T13:02:04Z'
          lastTransitionTime: '2022-11-23T13:02:03Z'
          reason: ReplicaSetUpdated
          message: ReplicaSet "bbs-jfedu-net-598fb758b6" is progressing.
          
    EOF
    #创建bbs-jfedu-net-service.yaml文件;
    cat>bbs-jfedu-net-service.yaml<<EOF
    kind: Service
    apiVersion: v1
    metadata:
      name: bbs-jfedu-net
      namespace: default
      uid: c259b7a1-4688-4e51-b5ce-7b9d0a600e15
      resourceVersion: '4636'
      creationTimestamp: '2022-11-23T13:16:20Z'
      labels:
        k8s-app: bbs-jfedu-net
      managedFields:
        - manager: dashboard
          operation: Update
          apiVersion: v1
          time: '2022-11-23T13:16:20Z'
          fieldsType: FieldsV1
          fieldsV1:
            'f:metadata':
              'f:labels':
                .: {}
                'f:k8s-app': {}
            'f:spec':
              'f:externalTrafficPolicy': {}
              'f:ports':
                .: {}
                'k:{"port":80,"protocol":"TCP"}':
                  .: {}
                  'f:name': {}
                  'f:port': {}
                  'f:protocol': {}
                  'f:targetPort': {}
              'f:selector':
                .: {}
                'f:k8s-app': {}
              'f:sessionAffinity': {}
              'f:type': {}
    spec:
      ports:
        - name: tcp-80-80-js226
          protocol: TCP
          port: 80
          targetPort: 80
          nodePort: 30286
      selector:
        k8s-app: bbs-jfedu-net
      clusterIP: 10.10.232.164
      clusterIPs:
        - 10.10.232.164
      type: LoadBalancer
      sessionAffinity: None
      externalTrafficPolicy: Cluster
    status:
      loadBalancer: {}
    EOF
    #基于yaml文件部署bbs-jfedu-net业务和Service;
    kubectl apply -f bbs-jfedu-net.yaml
    kubectl apply -f bbs-jfedu-net-service.yaml
    #查看bbs-jfedu-net业务是否部署成功;
    sleep 20
    kubectl get pods -n default
    
    • 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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
  • 相关阅读:
    linux学习2 — ubuntu 常用的命令总结
    6. Redis 发布与订阅
    AWS SAP-C02教程4--身份与联合身份认证
    FreeRTOS个人笔记-事件
    C# OpenCvSharp 环形文字处理 直角坐标与极坐标转换
    嘉为蓝鲸携手广州卷烟厂斩获信通院鼎新杯两大奖项
    C++初探 5-1(for循环)
    Linux scriptreplay回放你的高光时刻
    《操作系统-真象还原》10. 输入输出系统
    .NET的基元类型包括哪些?Unmanaged和Blittable类型又是什么?
  • 原文地址:https://blog.csdn.net/weixin_44681349/article/details/133795277