一、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@宿主机-192.168.0.155]$export:>uname -r3.10.0-862.11.6.el7.x86_64
[root@宿主机-192.168.0.155]$export:>cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) 
[root@宿主机-192.168.0.155]$export:>free -m
              total        used        free      shared  buff/cache   available
Mem:          31996         335       30840           8         820       31268
Swap:         16383           0       16383
[root@宿主机-192.168.0.155]$export:>

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

[root@宿主机-192.168.0.155]$export:>systemctl disable firewalld
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@宿主机-192.168.0.155]$export:>systemctl stop firewalld

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

[root@宿主机-192.168.0.155]$export:>yum install -y etcd kubernetes
[root@宿主机-192.168.0.155]$export:>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@宿主机-192.168.0.155]$export:>systemctl start etcd
[root@宿主机-192.168.0.155]$export:>systemctl start docker
[root@宿主机-192.168.0.155]$export:>systemctl start kube-apiserver
[root@宿主机-192.168.0.155]$export:>systemctl start kube-controller-manager
[root@宿主机-192.168.0.155]$export:>systemctl start kube-scheduler
[root@宿主机-192.168.0.155]$export:>systemctl start kubelet
[root@宿主机-192.168.0.155]$export:>systemctl start kube-proxy
[root@宿主机-192.168.0.155]$export:>

 到这里,这个单机版的Kubernetes集群环境就安装启动完成了。

接下来,我们可以在这个单机版的Kubernetes集群中上手练习了。

2、一个简单的Java web应用

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

3、启动MySQL服务

  首先作为MySQL服务创建一个RC定义文件: myslq-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  #指定api版本,此值必须在kubectl apiversion中
kind: ReplicationController   #指定创建资源的类型或者角色,这里是副本控制器 RC
metadata:       #资源的元数据/属性
  name: mysql  #资源的名字,在同一个namespace中必须唯一,这里的名字是RC
spec:           #specification of the resource content 指定该资源的内容
  replicas: 1  #Pod副本期待数量
  selector:
    app: mysql  #通过这个标签找到生产的Pod
  template:    #根据此模版创建Pod的副本(实例)
    metadata:
      labels:   #设定资源的标签     
        app: mysql  #Pod副本拥有的标签,对应RC的selector中app: mysql
    spec:
      containers:   #Pod内容器的定义部分
      - name: mysql   #容器的名称
        image: mysql  #容器对应的Docker Image
        ports:
        - containerPort: 3306 #容器应用监听的端口号
        env:   #注入容器内的环境变量
        - name: MYSQL_ROOT_PASSWORD
         value: "123456"
  • kind属性,用来表示此资源对象的类型,比如这里的值为"ReplicationController"表示这是一个RC;

  • spec一节中是RC的相关属性定义,比如spec.selector是RC的Pod标签(Label)选择器,即监控和管理拥有这些标签的Pod实例,确保当前集群上始终有且仅有relicas个Pod实例在运行这里我们设置replicas=1表示只能运行一个MySQL Pod实例;

  • 当集群中运行的Pod数量小于replicas时,RC会根据spec.template一节中定义的Pod模版来生成一个新的Pod实例,spec.template.metadata.labels指定了该Pod的标签,需要特别注意的是:这里的labels必须匹配之前的spec.selector,否则RC每次创建了一个无法匹配Label的Pod,就会不停地尝试创建新的额Pod,最终陷入"为他人作嫁衣裳"的悲惨世界中,永无翻身之时。

json格式化,便于人阅读:

{ 
  apiVersion: 'v1',
  kind:'ReplicationController',
  metadata: { name: 'mysql' },
  spec: 
   { 
    replicas: 1,
    selector: { app: 'mysql' },
    template: { metadata: { labels: { app: 'mysql' } } },
    spec: { 
      containers: [ { 
        name: 'mysql',
        image: 'mysql',
        ports: [ { containerPort: 3306 } ],
        env: [ { name: 'MYSQL_ROOT_PASSWORD', value: '123456' } ] 
        } 
      ] 
    } 
  } 
}

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

[root@宿主机-192.168.0.155]$export:>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@宿主机-192.168.0.155]$export:>kubectl create -f mysql-rc.yaml 
replicationcontroller "mysql" created

Kubernetes 通过template来生成pod,创建完后模板和pod就没有任何关系了,rc通过 labels来找对应的pod,控制副本。

接下来,我们用kubectl命令查看刚刚创建的RC:

[root@宿主机-192.168.0.155]$export:>kubectl get rc
NAME      DESIRED   CURRENT   READY     AGE
mysql     1         0         0         3m
[root@localhost export]# kubectl get pods
No resources found.
[root@localhost export]#

 之前的环境没有了,重新创建了新环境,继续写博客。

[root@localhost export]# 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@localhost export]# 

[root@localhost export]# 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@localhost export]# systemctl restart kube-apiserver.service
[root@localhost export]#

  之后重新创建RC

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

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

[root@localhost export]# vim mysql-svc.yaml 
 apiVersion: v1
 kind: Service
 metadata:
   name: mysql
 spec:
   ports:
     - port: 3306
   selector:
     app: mysql

  其中,metadata.name是Service的服务名(ServiceName): port属性则定义了Service的虚端口;spec.selector确定了哪些Pod副本(实例)对应到本服务。类似地,我们通过kubectl create 命令创建Service对象。

  运行 kubectl命令,创建service:

[root@localhost export]# kubectl create -f mysql-svc.yaml 
service "mysql" created

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

[root@localhost export]# kubectl get rc,svc
NAME       DESIRED   CURRENT   READY     AGE
rc/mysql   1         1         0         6m
NAME             CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
svc/kubernetes   10.254.0.1               443/TCP    1h
svc/mysql        10.254.206.115           3306/TCP   9s

  注意到MySQL服务被分配了一个值为10.254.206.115的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,内容如下:

[root@localhost export]# vim myweb-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: myweb
spec:
  #Pod的数量
  replicas: 2
  #spec.selector与spec.template.metadata.labels,这两个字段必须相同,否则下一步创建RC会失败。
  selector:
    app: myweb
  template:
    metadata:
      labels:
        app: myweb
   #容器组的定义
    spec:
      containers:
        #容器名称
        - name: myweb
        #容器对应的镜像
          image: kubeguide/tomcat-app:v1
          ports:
        #在8080端口上启动容器进程,PodIP与容器端口组成Endpoint,代表着一个服务进程对外通信的地址
          - containerPort: 8080
          env:
        #此处如果在未安装域名解析的情况下,会无法将mysql对应的IP解析到env环境变量中,因此先注释掉!
        # - name: MYSQL_SERVICE_HOST
        #   value: 'mysql'
        # - name: MYSQL_SERVICE_PORT
        #   value: '3306'

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

[root@localhost export]# kubectl create -f myweb-rc.yaml 
replicationcontroller "myweb" created
[root@localhost export]# kubectl get pods 
NAME          READY     STATUS              RESTARTS   AGE
mysql-v48vn   0/1       ContainerCreating   0          27m
myweb-kfds8   0/1       ContainerCreating   0          7s
myweb-v4xsq   0/1       ContainerCreating   0          7s

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

[root@localhost export]# vim myweb-svc.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@localhost ~]# kubectl create -f /export/myweb-svc.yaml 
service "myweb" created
[root@localhost ~]# kubectl get service 
NAME         CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes   10.254.0.1               443/TCP          2h
mysql        10.254.206.115           3306/TCP         46m
myweb        10.254.103.161          8080:30001/TCP   27s
[root@localhost ~]#

   至此,我们的第1个Kubernetes 例子搭建完成了。

5、通过浏览器访问网页

  经过上面的几个步骤,我们终于成功实现了 Kubernetes 上第1个例子的部署搭建工作,现在一起见证成果吧,在你的笔记本上打开浏览器,输入http://虚拟机 IP:30001/demo/。

  访问失败!我们看看怎么回事。

  首先确认关闭防火墙:

systemctl disable firewalld
systemctl stop firewalld

   看看本地telnet 端口试试:

[root@localhost ~]# kubectl describe svc myweb 
Name:     myweb
Namespace:    default
Labels:     
Selector:   app=myweb
Type:     NodePort
IP:     10.254.103.161
Port:     8080/TCP
NodePort:   30001/TCP
Endpoints:    
Session Affinity: None
No events.
[root@localhost ~]# telnet 10.254.103.161 8080 
Trying 10.254.103.161...
telnet: connect to address 10.254.103.161: Connection refused
[root@localhost ~]# 
[root@localhost ~]# kubectl get pods 
NAME          READY     STATUS              RESTARTS   AGE
mysql-v48vn   0/1       ContainerCreating   0          1h
myweb-kfds8   0/1       ContainerCreating   0          47m
myweb-v4xsq   0/1       ContainerCreating   0          47m
[root@localhost ~]#

 看到 pods 一直处于ContainerCreating状态,开始查找原因,执行如下命令:

[root@localhost ~]# kubectl describe pod myweb-kfds8
Name:   myweb-kfds8
Namespace:  default
Node:   127.0.0.1/127.0.0.1
Start Time: Thu, 27 Dec 2018 19:30:02 +0800
Labels:   app=myweb
Status:   Pending
IP:   
Controllers:  ReplicationController/myweb
Containers:
  myweb:
    Container ID:   
    Image:      kubeguide/tomcat-app:v1
    Image ID:     
    Port:     8080/TCP
    State:      Waiting
    Reason:     ContainerCreating
    Ready:      False
    Restart Count:    0
    Volume Mounts:    
    Environment Variables:  
Conditions:
  Type    Status
  Initialized   True 
  Ready   False 
  PodScheduled  True 
No volumes.
QoS Class:  BestEffort
Tolerations:  
Events:
  FirstSeen LastSeen  Count From      SubObjectPath Type    Reason    Message
  --------- --------  ----- ----      ------------- --------  ------    -------
  49m   49m   1 {default-scheduler }      Normal    Scheduled Successfully assigned myweb-kfds8 to 127.0.0.1
  49m   3m    14  {kubelet 127.0.0.1}     Warning   FailedSync  Error syncing pod, skipping: failed to "StartContainer" for "POD" with ErrImagePull: "image pull failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request.  details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)"

  49m 12s 216 {kubelet 127.0.0.1}   Warning FailedSync  Error syncing pod, skipping: failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"registry.access.redhat.com/rhel7/pod-infrastructure:latest\""
[root@localhost ~]#

   其中 Error syncing pod, skipping: failed to "StartContainer" for "POD" with ErrImagePull: "image pull failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request. details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)"

Error syncing pod, skipping: failed to "StartContainer" for "POD" with ImagePullBackOff: "Back-off pulling image \"registry.access.redhat.com/rhel7/pod-infrastructure:latest\""

解决方法:

方法一:
  yum install *rhsm*
  试了还不行
方法二:
  1. wget http://mirror.centos.org/centos/7/os/x86_64/Packages/python-rhsm-certificates-1.19.10-1.el7_4.x86_64.rpm
  2. rpm2cpio python-rhsm-certificates-1.19.10-1.el7_4.x86_64.rpm | cpio -iv --to-stdout ./etc/rhsm/ca/redhat-uep.pem | tee /etc/rhsm/ca/redhat-uep.pem 
  3. 前两个命令会生成/etc/rhsm/ca/redhat-uep.pem文件.
  4. docker pull registry.access.redhat.com/rhel7/pod-infrastructure:latest
[root@localhost ~]# docker pull registry.access.redhat.com/rhel7/pod-infrastructure:latest
Trying to pull repository registry.access.redhat.com/rhel7/pod-infrastructure ... 
latest: Pulling from registry.access.redhat.com/rhel7/pod-infrastructure
26e5ed6899db: Downloading [===================>                               ] 24.79 MB/63.82 MB
66dbe984a319: Download complete 
26e5ed6899db: Downloading [===================>                               ] 25.31 MB/63.82 MB
26e5ed6899db: Pull complete 
66dbe984a319: Pull complete 
9138e7863e08: Pull complete 
Digest: sha256:92d43c37297da3ab187fc2b9e9ebfb243c1110d446c783ae1b989088495db931
Status: Downloaded newer image for registry.access.redhat.com/rhel7/pod-infrastructure:latest
[root@localhost ~]# kubectl get pods
NAME          READY     STATUS    RESTARTS   AGE
mysql-v48vn   1/1       Running   0          2h
myweb-kfds8   1/1       Running   0          2h
myweb-v4xsq   1/1       Running   0          2h
[root@localhost ~]# kubectl describe pods myweb-v4xsq
Name:   myweb-v4xsq
Namespace:  default
Node:   127.0.0.1/127.0.0.1
Start Time: Thu, 27 Dec 2018 19:30:02 +0800
Labels:   app=myweb
Status:   Running
IP:   172.17.0.3
Controllers:  ReplicationController/myweb
Containers:
  myweb:
    Container ID:   docker://38b74cadef264969792845b6278f1421fed96bdfb1554d3a8c325c4fa07bca3e
    Image:      kubeguide/tomcat-app:v1
    Image ID:     docker-pullable://docker.io/kubeguide/tomcat-app@sha256:7a9193c2e5c6c74b4ad49a8abbf75373d4ab76c8f8db87672dc526b96ac69ac4
    Port:     8080/TCP
    State:      Running
      Started:      Thu, 27 Dec 2018 21:12:05 +0800
    Ready:      True
    Restart Count:    0
    Volume Mounts:    
    Environment Variables:  
Conditions:
  Type    Status
  Initialized   True 
  Ready   True 
  PodScheduled  True 
No volumes.
QoS Class:  BestEffort
Tolerations:  
Events:
  FirstSeen LastSeen  Count From      SubObjectPath   Type    Reason      Message
  --------- --------  ----- ----      -------------   --------  ------      -------
  1h    51m   2 {kubelet 127.0.0.1}       Warning   MissingClusterDNS kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to DNSDefault policy.
  51m   51m   1 {kubelet 127.0.0.1} spec.containers{myweb}  Normal    Pulled      Successfully pulled image "kubeguide/tomcat-app:v1"
  51m   51m   1 {kubelet 127.0.0.1} spec.containers{myweb}  Normal    Created     Created container with docker id 38b74cadef26; Security:[seccomp=unconfined]
  51m   51m   1 {kubelet 127.0.0.1} spec.containers{myweb}  Normal    Started     Started container with docker id 38b74cadef26
[root@localhost ~]#

 浏览器访问tomcat:

浏览访问java项目:

报错:Error:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.

解决办法: 临时在tomcat的hosts里写mysql IP,长久解决是dns。