美文网首页
Kubernetes入门

Kubernetes入门

作者: 阿汤哥_8d27 | 来源:发表于2021-06-11 17:33 被阅读0次

    一、Kubernetes是什么
      首先,它是一个全新的基于容器技术的分布式架构领先方案。这个方案虽然还很新,但是它是谷歌十几年依赖大规模应用容器技术的经验积累和升华的一个重要成果。实现资源管理的自动化,以及跨多个数据中心的资源利用率的最大化。

    其次,如果我们的系统设计遵循了Kubernetes的设计思想,那么传统系统架构中那些和业务没有多大关系的底层代码或功能模块,都可以立刻从我们的视线消失,我们不必再费心于负载均衡器和部署实施问题,不必再考虑引用或自己开发一个复杂的服务治理框架,不必再头疼于服务监控和故障处理模块的开发。使用Kubernets提供的解决方案,我们仅节省了不少于30%的开发成本,同时可以将精力更加集中于业务本身,而且由于Kubernetes提供了强大的自动化机制,所以系统后期的运维难度和运维成本大幅度降低。

    然后,Kubernetes是一个开发的开发平台。没有限定任何编程接口,所以不论是Java、Go、C++还是用Python编写的服务,都可以毫无困难地映射为Kubernetes的Service,并通过标准的TCP通信协议进行交互。此外,由于Kubernetes平台对现有的编程语言、编程框架、中间价没有任何侵入性,因此现有的系统很容器改造升级并迁移到Kubernetes平台上。

    最后,Kubernetes是一个完备的分布式系统支撑平台,Kubernetes具有完备的集群管理能力,包括多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和服务发现机制、内建智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、可扩展的资源自动调度机制,以及多粒度的资源配额管理能力。同时,Kubernetes提供了完善的管理工具,这些工具涵盖了包括开发、部署测试、运维监控在内的各个环节。因此Kubernetes是一个全新的基于容器技术的分布式架构解决方案,并且是一个一站式的完备的分布式系统开发和支撑平台。

    二、为什么要用Kubernetes
      使用Kubernetes的理由很多,最根本的一个理由就是:IT从来都是一个由新技术驱动的行业。

    Docker这个新兴的容器化技术当前已经被很多公司所采用,其从单机走向集群已成为必然,而云计算的蓬勃发展正在加速这一进程。Kubernetes作为当前唯一被业界广泛认可和看好的Docker分布式系统解决方案,可以预见,在未来几年内,会有大量的新系统选择它,不管这些系统是运行在企业本地服务器还是被托管到公有云上。

    使用Kubernetes又会收获哪些好处呢?

    首先,最直接的感受就是我们可以"轻装上阵"地开发复杂系统了。在采用Kubernetes解决方案之后,只需要一个精悍的小团队就能轻松应对。在这个团队里,一名架构师专注于系统"服务组件"的提炼,几名开发工程师专注于业务代码的开发,一名系统兼运维工程师负责Kubernetes的部署和运维,从此再也不用"996",这并不是因为我们少做了什么,而是因为Kubernetes已经帮我们做了很多。

    其次,使用Kubernetes就是在全面拥抱微服务架构。微服务架构的核心是将一个巨大的单体应用分解为很多小的互相连接的微服务,一个微服务背后可能有多个实例副本在支撑,副本的数量可能会虽社系统的负荷变化而进行调整,内嵌的负载均衡器在这里发挥了重要作用。微服务架构使得每个服务都可以由专门的开发团队开发,开发者可以自由选择开发技术,这对于大规模团队来说很有价值,另外每个微服务独立开发、升级、扩展,因此系统具备很高的稳定性和快速迭代进化能力。谷歌、亚马逊、eBay,等国内大厂也都采用了微服务架构,此次谷歌更是将微服务架构的基础设施直接打包到Kubernetes解决方案中,让我们有机会直接应用微服务架构解决复杂业务的架构问题。

    然后,我们的系统可以随时随地整体"搬迁"到公有云上。Kubernetes最初的目标就是运行在谷歌自家的公有云GCE中,未来会支持更多的公有云及是基于Openstack的私有云。同时,在Kubernetes的架构方案中,底层网络的细节完全被屏蔽,基于服务的Cluster IP甚至都无须我们改变运行期的配置文件,就能将系统从物理机环境中无缝迁移到公有云中,或者在服务高峰期将部分服务对应的Pod副本放入公有云中以提升系统的吞吐量,不仅节省了公司的硬件投入,还大大改善了客户体验。

    最后,Kubernetes系统架构具备了超强的横向扩容能力。对于互联网公司来说,用户规模就等价于资产,谁拥有更多的用户,就能在竞争中胜出。因此超强的横向扩容能力是互联网业务系统的关键指标之一。不用修改代码,一个Kubernetes集群即可从只包含几个Node的小集群平滑扩展到上百个Node的大规模集群,我们利用Kubernetes提供的工具,甚至可以在线完成集群扩容。只要我们的微服务设计得好,结合硬件或公有云资源的线性增加,系统就能够承受大量用户并发访问带来的的巨大压力。
    三、用一个简单实例介绍Kubernetes
    1、环境准备
      首先,我们开始准备Kubernetes的安装和相关镜像下载,这次我使用的是一台物理机作为学习环境,并且直连外网

    [root@VM-16-5-centos ~]# uname -r
    3.10.0-1160.11.1.el7.x86_64
    [root@VM-16-5-centos ~]# cat /etc/redhat-release
    CentOS Linux release 7.8.2003 (Core)
    [root@VM-16-5-centos ~]# free -m
                  total        used        free      shared  buff/cache   available
    Mem:           3789         508        2112           0        1168        3041
    Swap:             0           0           0
    

    (1) 关闭Centos自带的防火墙服务;

    [root@VM-16-5-centos ~]# systemctl disable firewalld
    [root@VM-16-5-centos ~]# systemctl stop firewalld
    

    (2) 安装etcd和Kubernetes软件(会自动安装Docker软件):

    [root@VM-16-5-centos ~]# yum -y install etcd kubernetes
    [root@VM-16-5-centos ~]# kubectl version
    Client Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.2", GitCommit:"269f928217957e7126dc87e6adfa82242bfe5b1e", GitTreeState:"clean", BuildDate:"2017-07-03T15:31:10Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}
    Server Version: version.Info{Major:"1", Minor:"5", GitVersion:"v1.5.2", GitCommit:"269f928217957e7126dc87e6adfa82242bfe5b1e", GitTreeState:"clean", BuildDate:"2017-07-03T15:31:10Z", GoVersion:"go1.7.4", Compiler:"gc", Platform:"linux/amd64"}
    

    (3) 按顺序启动所有的服务

    [root@VM-16-5-centos ~]#systemctl start etcd
    [root@VM-16-5-centos ~]#systemctl start docker
    [root@VM-16-5-centos ~]#systemctl start kube-apiserver
    [root@VM-16-5-centos ~]#systemctl start kube-controller-manager
    [root@VM-16-5-centos ~]#systemctl start kube-scheduler
    [root@VM-16-5-centos ~]#systemctl start kubelet
    [root@VM-16-5-centos ~]#systemctl start kube-proxy
    

    到这里,这个单机版的Kubernetes集群环境就安装启动完成了。
    接下来,我们可以在这个单机版的Kubernetes集群中上手练习了。
    2、一个简单的Java web应用
      这个例子比较简单,需要启动2个容器:Web App容器和MySQL容器,并且Web App容器需要访问MySQL容器。运行在Tomcat里的Web App,JSP页面通过JDBC直接访问MySQL数据库并展示数据。为了演示和简化的目的,只要程序正确连接到了数据库上,它就会自动完成对应的Table的创建与初始化数据的准备工作。所以,当我们通过浏览器访问此应用时,就会显示一个表格的页面,数据则来自数据库。


    image.png

    3、启动MySQL服务
      首先作为MySQL服务创建一个RC定义文件: mysql-rc.yaml,下面给出了该文件的完整内容和解释:

    在Kunbernetes集群中,你只需要为需要扩容的Service关联的Pod创建一个RC(Replication Controller),则该Service的扩容以至于后来的Service升级等头疼问题都迎刃而解。在一个RC定义文件中包括以下3个关键信息:
      (1)目标Pod的定义。
      (2)目标Pod需要运行的副本数量(Replicas)。
      (3)要监控的目标Pod标签(Label)。
    在创建好RC(系统将自动创建好Pod)后,Kubernetes会通过RC中定义的Label刷选出对应的Pod实例并实时监控其状态和数量,如果实例数量少于定义的副本数量(Replicas),则会根据RC定义的Pod模块来创建一个新的Pod,然后将此Pod调度到合适的Node上启动运行,直到Pod实例的数量达到预定的目标。这个过程完全是自动化的,无须人工干预。有了RC,服务的扩容就变成了一个纯粹的简单数字游戏了,只要修改RC中的副本数量即可。后续的Service升级也将通过修改RC来自动完成。
    
    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: mysql
    spec:
      replicas: 1
      selector:
        app: mysql
      template:
        metadata:
          labels:
            app: mysql
        spec:
          containers:
          - name: mysql
            image: mysql:5.7
            ports:
            - containerPort: 3306
            env:
            - name: MYSQL_ROOT_PASSWORD
              value: "123456"
    

    创建好 mysql-rc.yaml文件后,为了将它发布到kubernetes集群中,我们在Master节点执行命令:

    [root@VM-16-5-centos ~]# kubectl create -f mysql-rc.yaml
    error: error validating "mysql-rc.yaml": error validating data: [found invalid field app for v1.ReplicationControllerSpec, found invalid field containers for v1.ReplicationControllerSpec, found invalid field image for v1.ReplicationControllerSpec, found invalid field labels for v1.ReplicationControllerSpec, found invalid field metadata for v1.ReplicationControllerSpec, found invalid field spec for v1.ReplicationControllerSpec, found invalid field value for v1.ReplicationControllerSpec, found invalid field env for v1.ReplicationControllerSpec, found invalid field ports for v1.ReplicationControllerSpec]; if you choose to ignore these errors, turn validation off with --validate=false 
    

    从抛出的错误上看,应该是格式的问题,在yaml里面,结构通过缩进来表示,yaml不支持制表符tab缩进,而使用空格缩进。

    [root@VM-16-5-centos ~]#kubectl create -f mysql-rc.yaml 
    replicationcontroller "mysql" created
    

    Kubernetes 通过template来生成pod,创建完后模板和pod就没有任何关系了,rc通过 labels来找对应的pod,控制副本。
    接下来,我们用kubectl命令查看刚刚创建的RC:

    [root@VM-16-5-centos ~]#kubectl get rc
    NAME      DESIRED   CURRENT   READY     AGE
    mysql     1         0         0         3m
    [root@VM-16-5-centos ~]#kubectl get pods
    No resources found.
    
    [root@VM-16-5-centos ~]#kubectl describe rc
    Name:       mysql
    Namespace:  default
    Image(s):   mysql
    Selector:   app=mysql
    Labels:     app=mysql
    Replicas:   0 current / 1 desired
    Pods Status:    0 Running / 0 Waiting / 0 Succeeded / 0 Failed
    No volumes.
    Events:
      FirstSeen LastSeen    Count   From                SubObjectPath   Type        Reason      Message
      --------- --------    -----   ----                -------------   --------    ------      -------
      44m       34s     24  {replication-controller }           Warning     FailedCreate    Error creating: No API token found for service account "default", retry after the token is automatically created and added to the service account
    
    [root@VM-16-5-centos ~]#vim /etc/kubernetes/apiserver
     KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuot"
     去除KUBE_ADMISSION_CONTROL中的SecurityContextDeny,ServiceAccount,
     KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,ResourceQuota"
    [root@VM-16-5-centos ~]#systemctl restart kube-apiserver.service
    

    之后重新创建RC

    [root@VM-16-5-centos ~]#kubectl create -f mysql-rc.yaml
    Error from server (AlreadyExists): error when creating "mysql-rc.yaml": replicationcontrollers "mysql" already exists
    #之前创建的rc,需要删除掉,我们现在来删除
    [root@VM-16-5-centos ~]#kubectl delete -f mysql-rc.yaml
    replicationcontroller "mysql" deleted
    #发布到kubernetes集群,重新创建RC
    [root@VM-16-5-centos ~]#kubectl create -f mysql-rc.yaml
    replicationcontroller "mysql" created
    #查看RC
    [root@VM-16-5-centos ~]#kubectl get rc
    NAME      DESIRED   CURRENT   READY     AGE
    mysql     1         1         0         7s
    #查看Pod
    [root@VM-16-5-centos ~]# kubectl get pods
    NAME          READY     STATUS              RESTARTS   AGE
    mysql-lh61z   0/1       ContainerCreating   0          50m
    

    最后,我们创建一个与之关联的 Kubernetes Service——MySQL的定义文件 mysql-svc.yaml。

    apiVersion: v1
    kind: Service
    metadata:
      name: mysql
    spec:
      ports:
      - port: 3306
      selector:
        app: mysql
    

    运行 kubectl命令,创建service:

    [root@VM-16-5-centos ~]# kubectl create -f mysql-svc.yaml 
    service "mysql" created
    

    运行 kubectl 命令,可以查看到刚刚创建的service:

    [root@VM-16-5-centos ~]# kubectl get svc
    NAME         CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
    kubernetes   10.254.0.1      <none>        443/TCP    2h
    mysql        10.254.39.243   <none>        3306/TCP   10s
    

    注意到MySQL服务被分配了一个值为10.254.39.243的Cluster IP地址,这是一个虚地址,随后,Kubernetes集群中其他新创建的Pod就可以通过Service的Cluster IP+ 端口号3306来连接和访问它了。

    在通常情况下,Cluster IP 是在Service创建后,由Kubernetes 系统自动分配的,其他Pod无法预先知道某个Service的Cluster IP地址,因此需要一个服务发现机制来知道这个服务。为此,最初时,Kubernetes巧妙地使用率Linux环境变量来解决这个问题。现在我们只需要知道,根据Service的唯一名字,容器可以从环境变量中获取到Service对应的Cluster IP 地址和端口,从而发起 TCP/IP 连接请求了。
    3、启动Tomcat应用
    上面我们定义和启动了Mysql服务,接下来我们采用同样的步骤,完成Tomcat应用的启动过程。首先,创建对应的 RC 文件 myweb-rc.yaml,内容如下:

    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: myweb
    spec:
      replicas: 2
      selector:
        app: myweb
      template:
        metadata:
          labels:
            app: myweb
        spec:
          containers:
          - name: myweb
            image: kubeguide/tomcat-app:v1
            ports:
            - containerPort: 8080
            env:
            - name: MYSQL_SERVICE_HOST
              value: "mysql"
            - name: MYSQL_SERVICE_PORT
              value: "3306"
    

    注意,Tomcat容器内,应用将使用环境变量 MYSQL_SERVICE_HOST 的值连接MySQL服务。更安全可靠的用法是使用服务的名称 "mysql", 运行下面的命令,完成RC的创建和验证工作。

    [root@VM-16-5-centos ~]# kubectl create -f myweb-rc.yaml 
    replicationcontroller "myweb" created
    [root@VM-16-5-centos ~]# kubectl get rc
    NAME      DESIRED   CURRENT   READY     AGE
    mysql     1         1         0         1h
    myweb     2         2         0         9s
    [root@VM-16-5-centos ~]# kubectl get pods
    NAME          READY     STATUS              RESTARTS   AGE
    mysql-lh61z   0/1       ContainerCreating   0          1h
    myweb-31jp5   0/1       ContainerCreating   0          3m
    myweb-wl3td   0/1       ContainerCreating   0          3m
    

    最后,创建对应的Service:。以下是完整的yaml定义文件:

    apiVersion: v1
    kind: Service
    metadata: 
      name: myweb
    spec:
      type: NodePort
      ports:
        - port: 8080
          nodePort: 30001
      selector:
        app: myweb
    

    type=NodePort 和 nodePort=30001 的两个属性,表示此 Service开启了 NodePort方式的外网访问模式,在Kubernetes集群之外,比如在本机的浏览器里,可以通过 30001 这个端口访问myweb(对应 8080 的虚端口上)。

    运行 kubectl create 命令进行创建。

    [root@VM-16-5-centos ~]# kubectl create -f myweb-svc.yaml 
    service "myweb" created
    [root@VM-16-5-centos ~]# kubectl get svc
    NAME         CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
    kubernetes   10.254.0.1      <none>        443/TCP          3h
    mysql        10.254.39.243   <none>        3306/TCP         58m
    myweb        10.254.87.10    <nodes>       8080:30001/TCP   35s
    

    至此,我们的第1个Kubernetes 例子搭建完成了
    5、通过浏览器访问网页

    参考文档

    相关文章

      网友评论

          本文标题:Kubernetes入门

          本文链接:https://www.haomeiwen.com/subject/sbkveltx.html