此java web应用简单,是一个运行在Tomcat的Web App。如下图所示:
通过浏览器http协议访问此应用,会显示一个表格的页面,数据来自数据库。
此应用需要启动两个容器,web app容器和my sql容器,并且web app容器需要访问mysql容器。
在docker时代,假设我们再一个宿主机上启动了这两个容器,则我们需要将mysql容器的IP地址通过环境变量的方式注入web app容器中,同时需要将web app的8080端口映射到宿主机的8080端口。以便能在外部访问。
那么通过k8s如何实现呢?
环境准备
采用centos7作为开发环境。按照如下步骤快速安装k8s:
1.关闭centos防火墙
systemctl disable firewalld
systemctl stop firewalld
2.安装etcd和k8s(会自动安装docker)
yum install -y etcd kubernetes
3.安装好后,修改两个配置文件
docker的配置文件/etc/sysconfig/docker 修改OPTIONS内容为:
OPTIONS=’–selinux-enabled=false –insecure-registry gcr.io’
kubernetes apiserver配置文件为/etc/kubernetes/apiserver,把–admission_control参数中的ServiceAccount删除。
4.按顺序启动所有服务:
systemctl start etcd
systemctl start docker
systemctl start kube-apiserver
systemctl start kube-controller-manager
systemctl start kube-scheduler
systemctl start kubelet
systemctl start kube-proxy
至此,一个单机版的kubernetes集群环境安装启动完成。
启动mysql服务
首先为mysql服务创建一个rc定义文件:mysql-rc.yaml,下面给出该文件的完整内容和解释:
apiVersion: v1
kind: ReplicationController ——副本控制器RC
metatada:
name: mysql ——RC的全称,全局唯一
spec:
replicas: 1 ——pod副本期待数量
selector:
app: mysql ——拥有此标签的pod是符合目标的
template: ——根据此模板创建pod副本(实例)
metadata:
labels:
app: mysql ——pod副本拥有的标签,对应RC的selector
spec:
containers: ——pod内容器的定义部分
-name: mysql ——容器名称
image: mysql ——容器对应的docker image
ports:
– containerPort: 3306 ——容器暴露的端口号
env: ——注入到容器内的环境变量
-name: MYSQL_ROOT_PASSWORD
value: “123456”
文件中,kind属性表示此资源对象的类型,这里的值是ReplicationController ,说明这是一个RC。
spec是RC的相关属性定义,比如selector是RC的pod标签选择器,也就是pod中凡是label为mysql的都是所选择的。
然后监控和管理这些pod,确保始终有且只有replicas个pod实例运行。replicas=1表示只有1个pod实例。
当集群中运行的pod数量少于replicas时,会根据spec.template一节中定义的pod模板来生成一个新的pod实例。
spec.template.metadata.labels指定了新pod的标签,需要注意的是:这里的labels必须匹配之前的spec.selector,否则此RC每次创建一个无法匹配label的pod,会不断尝试创建新的pod。陷入死循环。
创建好yaml文件后,为了将其发布到b8s集群中,在master节点执行命令:
kubectl create -f mysql-rc.yaml
接下来可以用kubectl命令查看刚刚创建的RC:
kubectl get rc
查看pod创建情况,可以运行:
kubectl get pods
以上就创建了mysql的pod和RC。
最后我们要创建一个与之关联的k8s service(服务),也就是mysql的定义文件:
mysql-svc.yaml:
apiVersion: v1
kind: Service ——表明是service
metadata:
name: mysql ——service的全局唯一名称
spec:
ports:
-port: 3306 ——service提供服务的端口号
selector: ——service对应的pod拥有这里定义的标签
app: mysql
其中metadata.name是service的服务名(servicename);port属性定义了service虚端口;spec.selector确定了哪些pod副本(实例)对应到本服务。
运行kubectl,创建service:
kubectl create -f mysql-svc.yaml
运行kubectl,查看刚刚创建的service:
kubectl get svc
注意到mysql服务被分配了一个值为169.169.253.143的cluster IP地址,这是一个虚地址,随后k8s集群中其他新创建的pod可以通过该service的cluster IP+端口号来访问它。
通常情况下,cluster IP是在service创建后由k8s系统自动分配的,其他pod无法预先知道某个service的IP,因此需要一个服务发现机制(etcd)来找到这个服务。为此,最初,k8s利用Linux的环境变量来解决这个问题。现在我们只需要知道,根据service的唯一名字,容器可以从环境变量中获取到service对应的cluster Ip和端口,从而发起TCP连接请求。
以上就完成了mysql的服务的配置和启动,总结一下,首先是配置启动了mysql服务所需的pod和RC,创建好后,再创建mysql service(服务)。服务可以看成是用户(应用)与pod交互的接口,service屏蔽了k8s中的pod,全自动创建,运维的各种机制。使得用户(应用)只需要修改yaml文件就可以创建一个服务。而服务与用户(应用)以及服务与具体pod通信的机制都是TCP/IP。
启动Tomcat应用
上面我们定义并启动了mysql服务,接下来完成Tomcat应用的启动过程。
首先创建RC文件myweb-rc.yaml,内容如下:
kind: ReplicationController
metadata:
name: myweb
spec:
replicas: 5
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’
该RC文件类似于mysql的RC配置,这里就不在详细描述。
要注意的是,RC文件对应的tomcat容器中引用了MYSQL_SERVICE_HOST=mysql这个环境变量,而mysql恰好是我们之前定义的MYSQL服务的服务名,也就是通过引入该环境变量,能够获得mysql这个服务的cluster IP和端口,进而与mysql service通信。运行下面的命令,完成RC的创建和验证工作:
kubectl create -f myweb-rc.yaml
获得pod的状态
kubectl get pods
然后创建对应的service。与mysql service类似。
apiVersion: v1
kind: Service
metadata:
name: myweb
spec:
type: NodePort
ports:
– port: 8080
nodePort:30001
selector:
app: myweb
注意type=NodePort和nodePort=30001,表明此service开启了NodePort方式的外网访问模式,在k8s集群外,比如在本机的浏览器中,可以通过30001访问myweb服务(对应8080的虚端口)。也就是说30001是用户访问service的一个端口。
然后运行kubectl create命令进行创建:
kubectl create -f myweb-svc.yaml
运行kubectl,查看创建的service
kubectl get services
至此,一个简单的k8s例子搭建完成。
通过浏览器访问网页:
通过输入虚拟机IP:30001地址,可以访问网页界面。也就是查看tomcat服务。