单机版k8s集群搭建及Java Web应用部署

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010039418/article/details/86583867

注:本文基于CentOS 7.2编写

背景

最近在阅读《Kubernetes权威指南》这本书,该书最开始的例子是搭建单机版k8s集群,然后部署一个Java应用。跟着操作的过程中,遇到不少的坑,记录一下,也算是给后面的人提个醒吧。

项目介绍

该例子就是一个简单的Java Web应用,结构简单,是一个运行在Tomcat里的Web App,JSP页面通过JDBC直接访问MySQL数据库并展示数据。因此就两个主体,一个tomcat,一个MySQL。

环境准备

1、关闭防火墙,包括设置开启不启动。

systemctl disable firewalld
systemctl stop firewalld

2、k8s及etcd安装

yum install -y etcd kubernetes

以上操作会自动安装docker。

3、关闭docker的selinux

将/etc/sysconfig/docker配置文件中OPTIONS做如下修改,

OPTIONS='--selinux-enabled=false --log-driver=journald'

4、关闭kube-apiserver服务的ServiceAccount

/etc/kubernetes/apiserver文件中,KUBE_ADMISSION_CONTROL选项去掉ServiceAccount,

KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"

5、设置k8s相关服务开机启动,并启动服务

systemctl enable etcd docker kube-apiserver kube-controller-manager kube-scheduler kubelet kube-proxy
systemctl start etcd docker kube-apiserver kube-controller-manager kube-scheduler kubelet kube-proxy

至此,单机版k8s集群搭建完毕,我们可以查看下结点情况,

[root@CentOS-7-2 /home/k8s]# kubectl get node
NAME        STATUS    AGE
127.0.0.1   Ready     3m

部署应用

1、拉取镜像

上面说过我们有两个依赖,一个tomcat,一个MySQL,可以通过以下命令拉取这两个镜像,

docker pull mysql:5.5
docker pull kubeguide/tomcat-app

书上MySQL镜像并没有交代版本号,因此这就是天坑之一。不指定版本号,docker默认拉取的是最新的版本,目前,MySQL的最新版本是8.0.13,而作者对应tomcat使用的MySQL连接lib库是5.1.37,明显不匹配啊。。。。。这也就导致部署到最后面一直无法出现正常的表格页面。文章最后我们会详细看看这些坑最后呈现的报错。

2、创建rc及service

首先是MySQL的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.5
        ports:
        - containerPort: 3306
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123456"

除了images改成mysql:5.5外,其他和书本一致。对应的服务文件如下,

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

然后使用kubectl create命令创建资源,

[root@CentOS-7-2 /home/k8s]# ls
.  ..  mysql-rc.yaml  mysql-service.yaml 
[root@CentOS-7-2 /home/k8s]# kubectl create -f mysql-rc.yaml 
replicationcontroller "mysql" created
[root@CentOS-7-2 /home/k8s]# kubectl create -f mysql-service.yaml
service "mysql" created
[root@CentOS-7-2 /home/k8s]# kubectl get rc
NAME      DESIRED   CURRENT   READY     AGE
mysql     1         1         0         33s
[root@CentOS-7-2 /home/k8s]# kubectl get pod
NAME          READY     STATUS    RESTARTS   AGE
mysql-dmmht   1/1       Running   0          39s
[root@CentOS-7-2 /home/k8s]# kubectl get service
NAME         CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes   10.254.0.1      <none>        443/TCP          3d
mysql        10.254.34.195   <none>        3306/TCP         33s

如果出现创建rc成功,但是get pod却返回无该资源或者状态一直为ContainerCreating的,可以参考以下链接,尝试解决。
kubernetes新建rc成功却没创建pod
kubectl get pods一直显示ContainerCreating

MySQL相关资源创建完毕,接下来就是tomcat了,其RC定义文件如下,

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

这里是天坑之二,原书作者在env里指定了MYSQL_SERVICE_HOST属性为mysql,但是最后就是因为这里出错一直连接不上数据库,报的是无法解析mysql这个hostname。文章最后也会详细讲述一下这个错误。接着是对应的service文件,

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

同样,使用kubectl create命令创建资源,

[root@CentOS-7-2 /home/k8s]# ls
.  ..  mysql-rc.yaml  mysql-service.yaml  myweb-rc.yaml  myweb-service.yaml
[root@CentOS-7-2 /home/k8s]# kubectl create -f myweb-rc.yaml
replicationcontroller "myweb" created
[root@CentOS-7-2 /home/k8s]# kubectl create -f myweb-service.yaml 
service "myweb" created
[root@CentOS-7-2 /home/k8s]# kubectl get rc
NAME      DESIRED   CURRENT   READY     AGE
mysql     1         1         1         15m
myweb     1         1         1         11s
[root@CentOS-7-2 /home/k8s]# kubectl get pod
NAME          READY     STATUS    RESTARTS   AGE
mysql-dmmht   1/1       Running   0          15m
myweb-z99xn   1/1       Running   0          16s
[root@CentOS-7-2 /home/k8s]# kubectl get service
NAME         CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes   10.254.0.1      <none>        443/TCP          3d
mysql        10.254.34.195   <none>        3306/TCP         15m
myweb        10.254.115.49   <nodes>       8080:30002/TCP   15s

一切正常的情况下,我们就能如书上所说通过浏览器查看到demo的表格网页了。需要注意的是我们通过浏览器访问,用的是虚拟机的ip,和上面kubectl get service没关系,
在这里插入图片描述
往数据库里添加信息也是正常的,
在这里插入图片描述 在这里插入图片描述

各种报错

上面我们说到有两处坑,下面我们来看下这些坑呈现的错误是怎样的。

1、完全按照书本配置进行操作

这种情况,也就是使用最新的MySQL镜像,同时也配置了MYSQL_SERVICE_HOST属性。

此时在你使用浏览器访问的时候呈现的是Error:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException错误。
在这里插入图片描述
通过kubectl logs命令查看对应tomcat pod的日志,

[root@CentOS-7-2 /home/k8s]# kubectl logs -f myweb-xr12x
......
Connecting to database...
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.
......
Caused by: java.net.UnknownHostException: mysql: Name or service not known
	at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
	at java.net.InetAddress$1.lookupAllHostAddr(InetAddress.java:922)
	at java.net.InetAddress.getAddressesFromNameService(InetAddress.java:1316)
	at java.net.InetAddress.getAllByName0(InetAddress.java:1269)
	at java.net.InetAddress.getAllByName(InetAddress.java:1185)
	at java.net.InetAddress.getAllByName(InetAddress.java:1119)
	at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:191)
	at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:298)
	... 41 more
Goodbye!

可见,这里tomcat的java应用无法解析mysql这个hostname,因此我们删除MYSQL_SERVICE_HOST属性再来看下。

(注:我不知道怎么通过正确的配置来使得tomcat pod能正常解析mysql这个主机名,同样,删除这个配置后java应用又是怎么连接到数据库的,也不知道。这需要查看具体的java代码,目前暂无这个能力。希望有知道的读者能告知其中逻辑,感激不尽。)

2、使用最新MySQL镜像,不配置MYSQL_SERVICE_HOST属性

此时浏览器报错Error:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException,如下,
在这里插入图片描述
通过kubectl logs命令查看报错如下,

[root@CentOS-7-2 /home/k8s]# kubectl logs -f myweb-d70jq
......
Connecting to database...
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server.
......
Caused by: java.lang.NullPointerException
	at com.mysql.jdbc.ConnectionImpl.getServerCharset(ConnectionImpl.java:3004)
	at com.mysql.jdbc.MysqlIO.sendConnectionAttributes(MysqlIO.java:1908)
	at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1837)
	at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1207)
	at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2254)
Goodbye!
	at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2285)
	... 39 more

可见,此时出现空指针异常了,这就是由于JDBC的驱动不匹配导致的,也就是MySQL的版本不匹配。我们可以查看tomcat镜像里Java应用使用的MySQL库版本,

[root@CentOS-7-2 /home/k8s]# docker ps
CONTAINER ID        IMAGE                                                        COMMAND                  CREATED             STATUS              PORTS               NAMES
d92cf45e4498        kubeguide/tomcat-app:v1                                      "catalina.sh run"        6 minutes ago       Up 6 minutes                            k8s_myweb.35b7208f_myweb-d70jq_default_9a50c71f-1df4-11e9-a6f1-000c292e7489_c9b5b331
426cc40053e8        registry.access.redhat.com/rhel7/pod-infrastructure:latest   "/usr/bin/pod"           6 minutes ago       Up 6 minutes                            k8s_POD.24f70ba9_myweb-d70jq_default_9a50c71f-1df4-11e9-a6f1-000c292e7489_882ce6ef
59b9133cab18        mysql                                                        "docker-entrypoint.sh"   26 minutes ago      Up 26 minutes                           k8s_mysql.f6601b53_mysql-wgpg6_default_75573acd-1df1-11e9-a6f1-000c292e7489_bd53f046
bf54851bded5        registry.access.redhat.com/rhel7/pod-infrastructure:latest   "/usr/bin/pod"           28 minutes ago      Up 28 minutes                           k8s_POD.1d520ba5_mysql-wgpg6_default_75573acd-1df1-11e9-a6f1-000c292e7489_17a0bb95
[root@CentOS-7-2 /home/k8s]# docker exec -ti d92cf45e4498 /bin/bash
root@myweb-d70jq:/usr/local/tomcat# ls
LICENSE  NOTICE  RELEASE-NOTES	RUNNING.txt  bin  conf	include  lib  logs  temp  webapps  work   
root@myweb-d70jq:/usr/local/tomcat# cd webapps/demo/WEB-INF/lib/
root@myweb-d70jq:/usr/local/tomcat/webapps/demo/WEB-INF/lib# ls
mysql-connector-java-5.1.37.jar

可见,mysql-connector-java-5.1.37.jar版本和最新版本MySQL(8.0.13)不匹配。将MySQL换成5.5版本后,一切正常。

猜你喜欢

转载自blog.csdn.net/u010039418/article/details/86583867