本文是通過yum方式安裝Kubernetes,並部署tomcat+mysql實現Jave Web應用。此應用是JSP頁面通過JDBC訪問Mysql數據庫,只要程序正確連接到數據庫上,就會自動完成對應的Table的創建與初始化數據的準備工作。當我們通過瀏覽器訪問此應用時,就會顯示一個表格的頁面,數據則來自數據庫。
此應用需要啓動兩個容器:Web App容器和MySQL容器,並且Web App容器需要訪問MySQL容器。現在我們就來看看通過Kubernetes是如何實現Java Web應用的。
在繼續閱讀之前,我們需要對Kubernetes有一個基本的認識,需要了解它的原理、核心架構、核心組件和對象、以及各組件之間的聯繫等基礎概念,可以參考我的上一篇博文《初識Kubernetes(K8s):理論基礎》,http://blog.51cto.com/andyxu/2308937
系統環境
操作系統:Centos 7.5 64位
IP地址:192.168.2.238
一、安裝部署Kubernetes(K8s)
1、關閉Centos自帶的防火牆服務
注:Kubernetes集羣之間會有大量的網絡通信,在一個安全的內部網絡環境中建議關閉防火牆服務
[root@andyxu-test ~]# systemctl disable firewalld
[root@andyxu-test ~]# systemctl stop firewalld
2、安裝etcd和Kubernetes軟件(會自動安裝Docker軟件)
[root@andyxu-test ~]# yum -y install etcd kubernetes
注:yum方式安裝的kubernetes的版本是1.5.2
3、生成rhsm證書文件
[root@andyxu-test ~]# wget http://mirror.centos.org/centos/7/os/x86_64/Packages/python-rhsm-certificates-1.19.10-1.el7_4.x86_64.rpm
[root@andyxu-test ~]# 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
注:創建容器時需要從redhat站點下載pod-infrastructure:latest鏡像,如果沒有此證書文件會報錯,Pod會一直顯示ContainerCreating狀態。
4、修改docker和kube-apiserver的配置文件
docker配置文件爲/etc/sysconfig/docker,將OPTIONS的內容修改爲
OPTIONS='--selinux-enabled=false --insecure-registry gcr.io'
kube-apiserver配置文件爲/etc/kubernetes/apiserver,修改KUBE_ADMISSION_CONTROL的內容,將--admission-control參數中的ServiceAccount刪除。
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"
5、按順序啓動所有服務
[root@andyxu-test ~]# systemctl start etcd
[root@andyxu-test ~]# systemctl start docker
[root@andyxu-test ~]# systemctl start kube-apiserver
[root@andyxu-test ~]# systemctl start kube-controller-manager
[root@andyxu-test ~]# systemctl start kube-scheduler
[root@andyxu-test ~]# systemctl start kubelet
[root@andyxu-test ~]# systemctl start kube-proxy
二、創建並配置mysql容器
1、創建mysql的Deployment定義文件
mysql-dep.yaml文件內容如下:
apiVersion: extensions/v1beta1 #apiserver的版本
kind: Deployment #副本控制器deployment,管理pod和RS
metadata:
name: mysql #deployment的名稱,全局唯一
spec:
replicas: 1 #Pod副本期待數量
selector:
matchLabels: #定義RS的標籤
app: mysql #符合目標的Pod擁有此標籤
strategy: #定義升級的策略
type: RollingUpdate #滾動升級,逐步替換的策略
template: #根據此模板創建Pod的副本(實例)
metadata:
labels:
app: mysql #Pod副本的標籤,對應RS的Selector
spec:
containers: #Pod裏容器的定義部分
- name: mysql #容器的名稱
image: mysql:5.7 #容器對應的docker鏡像
volumeMounts: #容器內掛載點的定義部分
- name: time-zone #容器內掛載點名稱
mountPath: /etc/localtime #容器內掛載點路徑,可以是文件或目錄
- name: mysql-data
mountPath: /var/lib/mysql #容器內mysql的數據目錄
- name: mysql-logs
mountPath: /var/log/mysql #容器內mysql的日誌目錄
ports:
- containerPort: 3306 #容器暴露的端口號
env: #寫入到容器內的環境容量
- name: MYSQL_ROOT_PASSWORD #定義了一個mysql的root密碼的變量
value: "123456"
volumes: #本地需要掛載到容器裏的數據卷定義部分
- name: time-zone #數據卷名稱,需要與容器內掛載點名稱一致
hostPath:
path: /etc/localtime #掛載到容器裏的路徑,將localtime文件掛載到容器裏,可讓容器使用本地的時區
- name: mysql-data
hostPath:
path: /data/mysql/data #本地存放mysql數據的目錄
- name: mysql-logs
hostPath:
path: /data/mysql/logs #本地存入mysql日誌的目錄
- apiVersion:定義使用apiserver的哪個版本,可通過kubectl api-versions命令查看apiserver有哪些版本;
- kind:用來表明此資源對象的類型,比如這裏的值爲“Deployment”,表示這是一個deployment;
- spec:RS相關屬性定義,spec.selector是RS的Pod標籤(Label)選擇器,即監控和管理擁有這些標籤的Pod實例,確保當前集羣上始終有且僅有replicas個Pod實例在運行,這裏設置replicas=1表示只能運行一個Mysql Pod實例。
- spec.strategy:定義Pod的升級方案,Recreate表示刪除所有已存在的Pod,重新創建新的;RollingUpdate表示滾動升級,逐步替換的策略,滾動升級時支持更多的附加參數,例如設置最大不可用Pod數量,最小升級間隔時間等等。
- spec.template:當集羣中運行的Pod數量小於replicas時,RS會根據spec.template中定義的Pod模板來生成一個新的Pod實例,spec.template.metadata.labels指定了該Pod的標籤,需要特別注意的是,這裏的labels必須匹配之前的spec.selector。
- spec.template.spec.containers:容器的定義部分,包括容器的名稱、使用的docker鏡像、掛載數據卷、服務的端口號、變量等內容。
- spec.template.spec.volumes:需要掛載到容器裏的本地數據卷的定義部分,數據卷的名稱要與容器內掛載點的名稱一致,path定義本地的數據卷路徑。
2、創建deployment、RS、Pod和容器
創建過程需要先下載鏡像,時間會比較久,可喝杯茶撩撩旁邊的妹子,哈哈,請耐心等待
[root@andyxu-test ~]# kubectl create -f mysql-dep.yaml
deployment "mysql" created
3、查看創建好的deployment運行情況
[root@andyxu-test ~]# kubectl get deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
mysql 1 1 1 1 8s
注:都是1表示運行正常
4、查看ReplicaSet(RS)的運行情況
[root@andyxu-test ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
mysql-3238461207 1 1 1 6m
注:都是1表示運行正常
5、查看Pod的運行情況
[root@andyxu-test ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
mysql-3238461207-vvwt8 1/1 Running 0 56m
注:READY的值是1/1,並且STATUS的值是Running,表示運行正常
由於Pod的創建需要花費一些時間,在還沒有創建好容器時,STATUS的狀態會是ContainerCreating,表示正在創建容器,這時只需要等待。Pod創建好後,STATUS的狀態會是Running,這時可以通過docker ps命令查看容器運行的情況。
6、查看容器的運行情況
[root@andyxu-test ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5252cd76009a mysql:5.7 "docker-entrypoint..." 55 minutes ago Up 55 minutes k8s_mysql.23f88726_mysql-3238461207-vvwt8_default_72d7bff7-d81c-11e8-a729-000c29dabb02_6b15dcfc
f026e79ddad9 registry.access.redhat.com/rhel7/pod-infrastructure:latest "/usr/bin/pod" 55 minutes ago Up 55 minutes k8s_POD.1d520ba5_mysql-3238461207-vvwt8_default_72d7bff7-d81c-11e8-a729-000c29dabb02_668a091e
7、查看Pod裏容器的時間,檢查時間是否與本地時間一致
[root@andyxu-test ~]# kubectl exec mysql-3238461207-vvwt8 date
Thu Oct 25 15:06:15 CST 2018
注:exec後面跟pod的名稱
8、創建mysql的service定義文件
mysql-svc.yaml文件內容如下:
apiVersion: v1
kind: Service #表示Kubernetes Service
metadata:
name: mysql #Service的名稱
spec:
ports:
- port: 3306 #Service提供服務的端口號
selector:
app: mysql #Service對應的Pod的標籤
- metadata.name:Service的服務名稱
- spec.ports:Service提供的服務端口號,對應容器的服務端口號
- spec.selector:確定哪些Pod副本(實例)對應到此Service
9、創建Service
[root@andyxu-test ~]# kubectl create -f mysql-svc.yaml
service "mysql" created
10、查看Service的運行情況
[root@andyxu-test ~]# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 4h
mysql 10.254.144.64 <none> 3306/TCP 57s
kubernetes會給Service分配一個Cluster IP,這是個虛擬IP地址,此後集羣中的其他新創建的Pod就可以通過此Cluster IP+端口號的方式來連接和訪問mysql服務了。
三、創建並配置tomcat容器
1、創建tomcat的Deployment定義文件
myweb-dep.yaml文件的內容如下:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: myweb
spec:
replicas: 1
selector:
matchLabels:
app: myweb
strategy:
type: RollingUpdate
template:
metadata:
labels:
app: myweb
spec:
containers:
- name: myweb
image: kubeguide/tomcat-app:v1
volumeMounts:
- name: time-zone
mountPath: /etc/localtime
- name: tomcat-logs
mountPath: /usr/local/tomcat/logs
ports:
- containerPort: 8080
env:
- name: MYSQL_SERVICE_HOST
value: '10.254.144.64' #此處爲mysql服務的Cluster IP
- name: MYSQL_SERVICE_PORT
value: '3306'
volumes:
- name: time-zone
hostPath:
path: /etc/localtime
- name: tomcat-logs
hostPath:
path: /data/tomcat/logs
2、創建tomcat的deployment、RS、Pod和容器
[root@andyxu-test ~]# kubectl create -f myweb-dep.yaml
deployment "myweb" created
創建過程比較久,請耐心等待,pod的STATUS狀態爲Running時表示創建成功。
3、創建tomcat的Service定義文件
myweb-svc.yaml文件的內容如下:
apiVersion: v1
kind: Service
metadata:
name: myweb
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30001
selector:
app: myweb
此Service開啓了NodePort方式的外網訪問模式,端口爲30001,此端口會映射到tomcat容器的8080端口上。
4、創建Service
[root@andyxu-test ~]# kubectl create -f myweb-svc.yaml
service "myweb" created
5、查看Service的運行情況
[root@andyxu-test ~]# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 5h
mysql 10.254.144.64 <none> 3306/TCP 24m
myweb 10.254.246.56 <nodes> 8080:30001/TCP 39s
6、可使用curl命令測試tomcat服務是否能正常訪問
[root@andyxu-test ~]# curl http://192.168.2.238:30001
四、通過瀏覽器訪問網頁
1、如果30001端口不通的話,重新啓動、關閉firewalld防火牆
[root@andyxu-test ~]# systemctl start firewalld
[root@andyxu-test ~]# systemctl stop firewalld
注:因爲kubernetes會在iptables裏添加一些策略,需要再重新開啓關閉防火牆纔會關閉掉這些策略。
2、通過瀏覽器訪問http://192.168.2.238:30001/demo/
點擊“Add...”,添加一條記錄並提交
提交以後,數據就被寫入mysql數據庫裏了。
3、登陸mysql數據庫驗證
[root@andyxu-test ~]# docker exec -it 5252cd76009a /bin/bash
root@mysql-3238461207-vvwt8:/# mysql -uroot -p123456
mysql> use HPE_APP
mysql> select * from T_USERS;
我們可以繼續研究下這個例子,比如:
- 研究RS、Service等文件的格式。
- 熟悉kubectl的子命令。
- 手工停止某個Service對應的容器,觀察有什麼現象發生。
- 修改Deployment文件,改變pod副本的數量,重新創建,觀察結果。
此例子來源於《Kubernetes權威指南(第2版)》,我做了一些修改,以及報錯的處理,並且使用了Deployment來創建。