【云原生の微服务】4)学习微服务必须了解的K8s -百姓标王
暂无图片
登录 注册
暂无图片
暂无图片
暂无图片
暂无图片

【云原生の微服务】4)学习微服务必须了解的K8s

云世 2021-11-02
411

(文末提供最新【云原生系列课程】(DDD、K8s、ServiceMesh、微服务、Docker、Go语言学习)+【职场软技能】(架构师面试技能、管理实践、职场技能)免费课程资料获取途径)


----- 学习笔记 -----


为了进行本系列的学习,你需要有一个可用的Kubernetes集群。在本地开发环境中,可以使用Docker Desktop或是Minikube,也可以使用云平台上安装好的集群。前提要求是可以使用kubectl来访问集群
【面试专题】|7)技术&架构设计提升系列:面试题目及解题的正确姿势

Kubernetes 是一个可移植和可扩展的开源平台,用来管理容器化的工作负载和服务,它可以促进声明式的配置和自动化。Kubernetes 是 Google 基于自身运行大规模工作负载的丰富经验开发出来的,2014 年 Google 开源了 Kubernetes 项目,集合社区的智慧来让 Kubernetes 变得更好。Kubernetes 是目前容器编排领域上的事实标准。绝大多数云平台都提供了 Kubernetes 的支持,同时,它也是本系列中云原生应用的部署平台。

Kubernetes 集群 

部署 Kubernetes 之后将运行一个 Kubernetes 集群。Kubernetes 集群中包含很多不同的组件,分别运行在不同的节点(Node)上,其中,组件分成两类:控制平面(Control Plane)组件和节点组件,而节点可以是物理机器或虚拟主机。

 

控制平面组件分类中的组件如下表所示:

 

节点组件如下表所示: 

 

除了这些核心组件之外,还可以安装一些附加组件,如 DNS 服务器、Web 界面、容器资源监控和日志管理等。

 

下图给出了 Kubernetes 中各个组件之间的交互关系。

 

 

在实际的集群中,控制平面组件和工作节点组件通常部署在不同的机器上,包含控制平面组件的机器称为集群的主控节点(Master),包含节点组件的机器称为工作节点(Worker)。生产环境的集群中应该至少有 1 个主控节点和 3 个工作节点。

API 与对象

Kubernetes 的 API 采用与 Kubernetes 控制平面组件交互的方式,来管理 Kubernetes 集群。当需要与API 交互时,我们可以使用自带的 kubectl 工具,或使用不同编程语言的客户端库。

 

Kubernetes 的 API 中定义了很多不同类型的对象,这些对象的使用是声明式的,并且只声明了对象所期望的状态。每个对象中都包含 2 个字段,分别是 spec 和 status,其中 spec 描述了对象的期望状态,而 status 包含的是对象当前的状态。Kubernetes 会确保对象的最终状态与期望的状态保持一致。

 

在对象的描述中,每个对象都有名称和唯一的标识符,其中有一些字段是通用的。对象的名称由创建者提供,同一类对象的名称不能重复。对象的标识符由 Kubernetes 自动生成,其标签是添加到对象上的名值对,标签主要用来选择满足条件的对象。注解同样以名值对的形式出现,只不过注解的作用是添加附加的信息。从作用上来说,注解的作用类似于 Java 中的注解,很多 Kubernetes 上的框架和第三方库都允许使用自定义的注解来进行配置。

 

本节中对相关对象的描述都使用 YAML 格式。

Pod 

Kubernetes 中的 Pod 表示由一个或多个容器组成的分组。Pod 里面的容器共享一些资源,包括存储、网络和每个容器的运行配置。我们可以把 Pod 看成是一个应用运行的逻辑主机,相当于一个物理机器或虚拟主机,其中的容器是紧密耦合的。每个 Pod 都有唯一的 IP 地址,其中的容器共享同一个 IP 地址和端口范围,相互之间可以通过 localhost 访问。Pod 还可以使它的容器访问其定义的共享的存储卷(volume),通过这种方式,可以实现 Pod 容器之间的数据共享。

 

Pod 是 Kubernetes 中调度和运行的基本单元,但在 Kubernetes 上并不能直接运行容器,而是要把容器放在 Pod 中运行,Pod 再把其中的全部容器调度到同一个集群节点上运行。

控制器 

作为基本的运行单元,Pod 缺少相应的管理功能。如果一个 Pod 在运行中出现错误,并不会自动创建新的 Pod 来替代它;如果需要管理 Pod,则应该利用 Kubernetes 提供不同类别的控制器,包括副本集、部署、有状态集和守护程序集。

副本集

副本集(ReplicaSet)保证在任何时候都有给定数量的 Pod 副本。当创建副本集时需要指定一个创建 Pod 的模板,同时确定 Pod 的选择器,并给出期望的 Pod 副本数量。在运行时,副本集根据指定的 Pod 选择器来监控当前 Pod 副本的数量,如果副本数量小于期望值,则根据 Pod 模板来创建新的 Pod。一般用标签作为 Pod 的选择器。

 

下面代码中的 YAML 文件描述了包含 3 个 Pod 副本的副本集,每个 Pod 中只有一个 Nginx 容器,每个 Pod 上都添加了名称为 app、值为 nginx 的标签。副本集使用这个标签作为包含的 Pod 的选择器,在 spec.selector.matchLabels 中指定。spec.containers 指定的是创建 Pod 的模板。

    apiVersion: apps/v1
    kind: ReplicaSet
    metadata:
    name: nginx
    spec:
    replicas: 3
    selector:
    matchLabels:
    app: nginx
    template:
    metadata:
    labels:
    app: nginx
    spec:
    containers:
    - name: nginx
    image: nginx:1.17
    ports:
    - containerPort: 80

    部署

    部署(Deployment)在副本集上提供了对 Pod 的更新功能,每个部署都有对应的副本集。当部署中创建的 Pod 模板发生变化时,这些 Pod 都需要被更新。在更新时,Kubernetes会创建一个新的副本集来管理新的 Pod,当更新完成后,旧的副本集会被删除。

     

    部署可以采用不同的策略来更新这些 Pod,最常用的策略是滚动更新,它可以保证在更新过程中服务不间断。在进行滚动更新时,Kubernetes首先会创建新的副本集中的 Pod,再删除已有副本集中的 Pod。这个过程是交替进行的:在没有足够数量的新 Pod 运行之前,不会删除已有的 Pod;同样的,在没有足够数量的已有 Pod 被删除之前,不会创建新的 Pod。

     

    下面代码中的 YAML 文件创建了包含 3 个 Pod 副本的部署,它与上一小节中的副本集 YAML 的文件的区别在于,kind 的值是 Deployment。 

      apiVersion: apps/v1
      kind: Deployment
      metadata:
      name: nginx
      spec:
      replicas: 3
      selector:
      matchLabels:
      app: nginx
      template:
      metadata:
      labels:
      app: nginx
      spec:
      containers:
      - name: nginx
      image: nginx:1.17
      ports:
      - containerPort: 80

      有状态集

      副本集中的 Pod 没有标识符,不能进行区分,它唯一保证的是所包含的 Pod 总数。有些应用对运行的实例有启动顺序和唯一性的要求,典型的例子是通过多个实例组成集群的服务,如 Cassandra 和 RabbitMQ 等。这些应用要求实例有固定且唯一的网络标识,才能正确的建立集群,对于这样的应用,应该使用有状态集(StatefulSet)来管理。

       

      有状态集中的 Pod 都有唯一不变的标识符,这个标识符由有状态集的名称和 Pod 的序号组成。如果有状态集的名称是 cassandra,同时期望的 Pod 副本数量是 3,那么 Pod 的名称分别是 cassandra-0、cassandra-1 和 cassandra-2。有状态集需要一个对应的服务来提供 Pod 的 DNS 名称。

       

      有状态集在创建和扩展时有特殊的限制,如果一个有状态集期望的 Pod 副本数量是 N,那么有状态集会从 0 开始依次创建这些 Pod,在第 1 个 Pod 正常运行之前,不会创建第 2 个Pod;在删除 Pod 时,则是从第 N 个 Pod 开始反向依次删除。

       

      下面代码中的 YAML 文件创建了一个有状态集及其关联的服务。 

        apiVersion: v1
        kind: Service
        metadata:
        name: nginx
        labels:
        app: nginx
        spec:
        ports:
        - port: 80
        name: web
        clusterIP: None
        selector:
        app: nginx
        ---
        apiVersion: apps/v1
        kind: StatefulSet
        metadata:
        name: nginx
        spec:
        replicas: 3
        selector:
        matchLabels:
        app: nginx
        serviceName: nginx
        template:
        metadata:
        labels:
        app: nginx
        spec:
        containers:
        - name: nginx
        image: nginx:1.17
        ports:
        - containerPort: 80
        name: web

        在下面的 Pod 列表中你可以看到 Pod 的名称。 

          NAME      READY   STATUS    RESTARTS   AGE
          nginx-0 1/1 Running 0 35m
          nginx-1 1/1 Running 0 35m
          nginx-2 1/1 Running 0 35m

          守护程序集

          守护程序集(DaemonSet)确保在全部或部分的集群节点上运行 Pod,每个节点上最多运行一个 Pod 副本。如果应用需要执行的任务与节点相关,则应该使用守护程序集,比如收集日志和节点性能指标数据的应用,都应该使用守护程序集来部署。

           

          下面代码中的 YAML 文件创建了一个守护程序集。

            apiVersion: apps/v1
            kind: DaemonSet
            metadata:
            name: nginx
            labels:
            app: nginx
            spec:
            selector:
            matchLabels:
            app: nginx
            template:
            metadata:
            labels:
            app: nginx
            spec:
            containers:
            - name: nginx
            image: nginx:1.17
            ports:
            - containerPort: 80

            服务

            应用在运行时经常需要为其他应用提供服务。在使用控制器管理应用的 Pod 时,Pod 的 IP 地址会随着 Pod 的创建和删除而发生变化。因此,我们不能使用 Pod 的 IP 地址作为访问服务的方式。Kubernetes 中的服务(Service)作为一组 Pod 的抽象,定义了如何访问这些 Pod,

            它实现了服务发现和负载均衡两项重要的功能。

             

            在创建服务时需通过选择器来选择服务所对应的 Pod,应用服务的消费者使用服务的地址来访问 Pod,实际的访问请求会被分发到服务所对应的某个 Pod 上。当 Pod 发生变化时,服务会自动更新所对应的 Pod 列表。

             

            下表给出了服务的几种类型。


            下面代码中的 YAML 描述了一个类型为 NodePort 的服务。 

              apiVersion: v1
              kind: Service
              metadata:
              name: nginx
              spec:
              type: NodePort
              ports:
              - port: 8080
              targetPort: 80
              protocol: TCP
              name: http
              selector:
              app: nginx 

              在服务创建之后,服务的使用者可以有两种方式来发现服务。

               

              第一种方式是使用 Pod 的环境变量。在 Pod 运行时,每个服务的主机名和端口都会被自动添加到环境变量中,对应的环境变量名称是在服务名称之后添加 _SERVICE_HOST 和 _SERVICE_PORT 后缀,并且把服务名称转换成大写,把破折号替换成下划线。比如,如果服务名称是 cassandra,那么所对应的环境变量名称分别是 CASSANDRA_SERVICE_HOST 和 CASSANDRA_SERVICE_PORT。

               

              第二种方式是使用 DNS 名称。如果服务的访问者和服务的 Pod 在同一个名称空间中,则直接使用服务的名称进行访问即可;如果在不同的名称空间,则需要使用服务“名称.名称空间”的形式,如 cassandra.demo。

              存储卷

              容器运行时对内部文件所做的修改是瞬时的,当容器停止之后,相关的修改会丢失,如果应用具备第 03 课时中云原生应用的无状态特征,这并不是一个问题,反而是正确的做法。但是应用所依赖的支撑服务,绝大部分是有状态的,比如数据库和消息中间件等。

               

              Kubernetes 中的卷(Volume)是存储的抽象表示,解决了数据的持久化问题,卷与使用它的 Pod 具有相同的生命周期。Pod 中的容器可以使用卷共享数据,对于运行在 Pod 中容器里面的应用来说,卷就是文件系统上的一个目录,其中包含了可以访问的文件。Kubernetes 支持不同类型的卷,包括云平台提供的实现和第三方存储服务。

               

              在实际的 Kubernetes 集群中,数据存储通常需要进行统一管理,有专门的服务负责提供存储,而 Pod 是存储的消费者。

               

              Kubernetes 提供了两个对象,即持久卷和持久卷要求,持久卷可以由管理员手动创建,或者由存储服务动态创建,用户则以持久卷要求的形式来声明所需要使用的持久卷的大小和访问模式;持久卷要求可以与手动创建的持久卷进行绑定,如果需要动态创建,则由存储服务完成创建之后,再进行绑定。一旦完成绑定,持久卷可以用类似卷的方式来访问。

               

              下面代码中的 YAML 文件描述了一个容量为 1G 的持久卷,使用的存储类是 standard。 

                apiVersion: v1
                kind: PersistentVolume
                metadata:
                name: pv
                spec:
                storageClassName: standard
                capacity:
                storage: 1Gi
                accessModes:
                - ReadWriteOnce
                hostPath:
                path: "/mnt/data" 

                下面代码中的 YAML 文件描述了一个持久卷要求,所请求的空间大小是 1G,刚好可以由上面 YAML 文件中的持久卷来满足。 

                  apiVersion: v1
                  kind: PersistentVolumeClaim
                  metadata:
                  name: pvc
                  spec:
                  storageClassName: standard
                  accessModes:
                  - ReadWriteOnce
                  resources:
                  requests:
                  storage: 1Gi 

                  如果持久卷是动态创建的,则需要使用存储类来描述不同的存储方式,存储类通常由存储服务提供。在持久卷要求中,声明所需要使用的存储类后,它对应的存储服务会负责创建持久卷。

                   

                  下面代码的 YAML 文件中,部署中 Pod 里的 volumes 声明中的 persistentVolumeClaim 引用的持久卷要求的名称是pvc,与上面的YAML文件相对应。 

                    apiVersion: apps/v1
                    kind: Deployment
                    metadata:
                    name: nginx
                    labels:
                    app: nginx
                    spec:
                    replicas: 1
                    selector:
                    matchLabels:
                    app: nginx
                    template:
                    metadata:
                    labels:
                    app: nginx
                    spec:
                    volumes:
                    - name: data
                    persistentVolumeClaim:
                    claimName: pvc
                    containers:
                    - name: nginx
                    image: nginx:1.17
                    ports:
                    - containerPort: 80
                    volumeMounts:
                    - mountPath: "/usr/share/nginx/html"
                    name: data

                    任务和定时任务

                    当需要执行一次性任务时,我们可以使用任务对象在创建任务时指定需要运行的 Pod 模板。当需要定期执行任务时,则可以使用定时任务对象,在创建时,需要指定定时任务的 cron 表达式。

                     

                    下面代码中的 YAML 文件描述了执行一次的任务。

                      apiVersion: batch/v1
                      kind: Job
                      metadata:
                      name: job-hostname
                      spec:
                      template:
                      spec:
                      containers:
                      - name: busybox
                      image: busybox
                      command:
                      - hostname
                      restartPolicy: Never
                      backoffLimit: 1

                      下面代码中的 YAML 文件描述了每分钟执行一次的定期任务,定期任务在每次执行时都会创建新的 Job 对象。 

                        apiVersion: batch/v1beta1
                        kind: CronJob
                        metadata:
                        name: cronjob-date
                        spec:
                        schedule: "* * * * *"
                        jobTemplate:
                        spec:
                        template:
                        spec:
                        containers:
                        - name: busybox
                        image: busybox
                        command:
                        - date
                        restartPolicy: OnFailure

                        配置表

                        在第 03 节介绍云原生应用的时候,我们提到了配置外部化,当它运行在 Kubernetes 上时,应该使用配置表(ConfigMap)来管理配置。配置表可以看成是包含名值对的哈希表。

                         

                        Spring Boot 应用使用 application.properties 文件来管理配置。下面代码中的 ConfigMap 对象,仅包含一个名为 application.properties 的配置项,其对应值是 application.properties 文件的实际内容。 

                          apiVersion: v1
                          kind: ConfigMap
                          metadata:
                          name: app-config
                          data:
                          application.properties: |-
                          server.port = 9090
                          spring.application.name = myapp 

                          下面代码中的 YAML 文件创建了 Spring Boot 应用的部署。在 Pod 模板中,我们从配置表中创建了一个存储卷,配置表中的每个名值对都会被转换成一个文件:文件名是名称,而文件的内容是相应的值。应用容器把该存储卷映射到 /etc/config 目录上,通过环境变量 SPRING_CONFIG_LOCATION 可以让 Spring Boot从/etc/config 目录中加载配置文件,从而应用 application.properties 文件的配置。 

                            apiVersion: apps/v1
                            kind: Deployment
                            metadata:
                            name: demo-app
                            labels:
                            app: demo-app
                            spec:
                            replicas: 1
                            selector:
                            matchLabels:
                            app: demo-app
                            template:
                            metadata:
                            labels:
                            app: demo-app
                            spec:
                            containers:
                            - name: app
                            image: localhost:5000/demo-app
                            env:
                            - name: SPRING_CONFIG_LOCATION
                            value: /etc/config/
                            volumeMounts:
                            - name: config-volume
                            mountPath: /etc/config
                            volumes:
                            - name: config-volume
                            configMap:
                            name: app-config


                            总结

                             

                            Kubernetes是本系列所介绍的云原生微服务应用的运行平台。本节对Kubernetes中的基本概念进行了介绍,包括Kubernetes集群、Pod、副本集、部署、有状态集、守护程序集等,还介绍了服务、存储卷、任务和定时任务、以及配置表的相关内容。


                            如果你觉得这个系列有价值,也欢迎转发给有需要的朋友。



                            喜欢就|关注|转发|点赞|订阅专题吧
                            公号专题
                            数据库
                            文章转载自云世,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                            评论

                            相关内容推荐

                            秒收录软件seo 推广北辰区seo全网营销上海seo测试服务已解决seo优化前需要做什么工作seo网盘最新seo优化哪个品牌好大沥seo优化销售seo推广解决方案广告seo操作员是什么意思淮南燕郊seoSEO搜了网百度权重用seo需要多少费用seo兼职去哪找运营有利于seo官网源码初学者自学seo 分类大足区seo优化批发价格seo网络推广产品分类日照seo搜索优化怎么做祖庙seo优化哪家专业怎么衡量seo优化专业的关键词seo外包焦作seo优化教程seo优化的自我领悟seo业务培训学费贵不贵无锡seo关键词推广seo实战密码 课件seo的官网配置温州新网站seoseo优化文章有哪些方法seo能谋善断的6个方法海珠区seo优化收费seo深度解析相关商品seo和sem哪个适合新手外推上海口碑好的seo优化包括什么重庆小排名seo人才厦门在线seo信息优化seo兼职招聘信息广告阳泉专业seo优化栾川seo优化选哪家福州专业seo优化营销seo兼职招聘关键词seo逆向技术seo推广学习中心seo教程辽宁标准抖音seo优化哪家好武汉seo优化批发沈阳品牌抖音seo优化要求达州seo网络推广代理商seo虫虫教程蓬莱seo关键词优化广东百度seo付费推广小姐词灰色词网站SEOseo挖掘机深圳seo外包关键词推广南浔区seo推广哪家好seo薪酬哈尔滨seo排名服务优化seo价格查询晋安区一般seo大概费用佛山市页面seo优化南通seo推广哪家好重庆关键词seo排名网站万紫园seo舞蹈国际连锁南沙seo排名优化推广seo一个月多少钱2018seo优化三大误区垫江一站式seo推广费用是多少seo提高网站权重方案墟沟seo网络优化多少钱闽侯有效的seo联系方式阿拉尔seo 网络推广价格seo定位的关键词北京SEO刻羽云肇庆seo网络推广服务白云seo优化公司seo优化人员招聘石家庄seo网站推广福州市提升seo关键词排名模式小微企业不玩seo优化鹤壁百度seo关键词排名代理仙桃外包seo推广多少钱晋安区有效的seo报价短视频seo营销获客运营张家界搜狗seo优化公司福州市提升seo关键词排名模式广东seo营销哪家好清远市企业站seo哪家好阳泉seo全网营销价格seo_lukhyun身高aso对SEO的影响宁德市seo优化报价前端能做的seoseo是需要付费才能使用海南怎么学seo关键词优化策略广州站外seo推广费用长沙新站seo优化代理丰南seo优化有哪些自学seo要学会什么运营南岸知名seo优化哪家好淘宝客多产品seo广东长沙seo优化晋中抖音搜索排名seo怎么做微博seo使用了哪些优化技巧十堰便宜的seo推广公司排名莞城区seo什么是seo视频脚本怎么写网址seo关键词优化抖音seo软件厂家包头seo优化排名seo 搜索 关键词百度竞价托管seo教程长治抖音seo搜索优化排名seo博客攻略推广三明抖音搜索排名seo怎么做加盟seo费用谷歌seo易海创腾怎么样seo长尾词怎么写vue的seo关键词优化问题阿克苏seo 网络推广代理沈阳培训seo机构北京网站百度seo佛山seo优化信誉保证桂林seo推广推荐浙江seo推广优质团队福清网页seo哪家好软文seo价值黄骅seo整站优化报价保定seo推广公司哪家好西八里庄关键词seo优化前端seo是什么意思城口中小企业seo推广代运营灰帽seo营销排名seo排序算法自学seo多久佛山网络推广seo渠道滁州seo推广品牌公司北京竞价排名seo嘉兴seo厦门公司电话长治seo优化费用是多少南皮关键词seo优化多少钱浙江市场seo优化值多少钱医疗seo实战太原seo网络推广方案服务南阳专业seo公司南通抖音seo优化搜索排名宁波seo服务竞价泸西seo优化价格湖北房地产seo推广哪家好辛集seo关键词排名优化哪家好北屯seo 网络推广联系方式郑州的seo发展前景合肥价格低seo搜索优化百度竞价代理商seo大连seo优化排行大良seo优化策略互联网seo优化质量推荐全网霸屏推广seo教程seo策略分析如何找seo工作seo专员引流乐从seo优化学习seo如何制作目录河南全网seo推广优势是什么城口中小企业seo推广效果江西南昌网站seo公司长沙seo优化软件哪个好辽宁综合抖音seo优化信息中心seo优化对店铺的意义浙江seo网络推广优化杭州seo推广费用公司广东快速seo关键词优化服务徐州seo关键词排名优化金水区seo推广在哪里保定seo网站排名优化岳阳专业seo优化公司天津整站seo价格seo专业推广霸屏襄阳计算机seo推广哪里好金华seo开户公司无锡短视频seo好做吗余杭区网络seo营销推广seo网络营销推广哪家做的好南昌seo公司排名英文seo盈利模式天门白酒seo推广哪家好昆明seo平台好做吗铁门关seo网络营销咨询河北百度seo推广优化怀化seo优化公司在哪里seo付款系统源码收录孝感seo技术seo排名课程咨询电话谷歌seo会自己做网站吗seo整站优化多少钱推广宜昌茶叶seo推广怎么做东西湖seo排名分析湘西搜狗seo优化方案洋河seo优化公司宿豫区seo关键词优化价格保定seo推广公司哪家好綦江区中小企业seo推广哪家好嘉善一站式seo推广性价比

                            合作伙伴

                            百姓标王

                            龙岗网络公司
                            深圳网站优化
                            龙岗网站建设
                            坪山网站建设
                            百度标王推广
                            天下网标王
                            SEO优化按天计费
                            SEO按天计费系统