將專案遷移到kubernetes平臺是怎樣實現的
將專案遷移到k8s平臺是怎樣實現的?
-
製作映象
-
控制器管理Pod
-
Pod資料持久化
-
暴露應用
-
對外發布應用
-
日誌/監控
1 製作映象分為三步:
- 第一基礎映象,是基於哪個作業系統,比如Centos7或者其他的
- 第二步中介軟體映象,比如服務映象,跑的像nginx服務,tomcat服務
- 第三步專案映象,它是服務映象之上的,將你的專案打包進去,那麼這個專案就能在你這個服務映象裡面運行了
一般運維人員都是提前將映象做好,而開發人員就能直接拿這個映象去用,這個映象一定要符合現在環境部署的環境。
2 控制器管理 pod
也就是k8s去部署這個映象了,一般我們都會去拿控制器去部署,用的最多的就是 deployment
-
Deployment:無狀態部署
-
StatefulSet:有狀態部署
-
DaemonSet:守護程序部署
-
Job & CronJob:批處理
無狀態和有狀態的有什麼區別?
有狀態的是有身份的,比如網路ID、儲存、這個兩個是提前規劃好的,有序啟動/停止
持久化與非持久化
3 Pod 資料持久化
pod資料持久化主要是因對一個應用程式說的,比如開發一個專案,這個專案有沒有落地到本地檔案,如果有落的話,就保證他持久的有了,那就必須要用到pod資料的持久化了。
容器部署過程中一般有以下三種資料:
-
啟動時需要的初始資料,可以是配置檔案
-
啟動過程中產生的臨時資料,該臨時資料需要多個容器間共享
-
啟動過程中產生的持久化資料
4 暴露應用
在 k8s中,部署一個deployment,它是無法對外進行訪問的,即其他應用程式要想訪問部署的deployment,它找不到該怎麼去訪問。為什麼去這麼講,因為deployment一般都是多副本的去部署,有可能會分佈在不同的節點之上,而且重建 pod ip也會變,重新發布一下也會變了,所以沒有辦法去固定去訪問哪個pod,即使固定了,其他的pod也訪問不了。要想做到多個 pod 都去提供服務的話,前面有必須要加一個負載均衡,提供一個訪問入口,只有訪問這個統一入口,才能轉發到後端多個pod上,只要訪問這個Cluster IP就能轉發到後端的pod上。
Service
-
Service 定義了 Pod 的邏輯集合和訪問這個集合的策略
-
Service 引入為了解決Pod的動態變化,提供服務發現和負載均衡
-
使用 CoreDNS 解析 Service 名稱
5 對外發布應用
暴露出去之後呢,也就是需要讓使用者去訪問,比如搭建一個電商網站,讓使用者去訪問,ingress相對於service,它是一個互補的狀態,彌補了各自,service主要提供了叢集內部的訪問,也可以暴露一個TCP/UDP的埠,而ingress主要是一個7層的轉發,也就是提供一個統一的入口,只要訪問ingress controller,它就能幫你轉發你部署所有的專案,也就是所有的專案都使用域名去訪問。
首先開發者將程式碼部署到你的程式碼倉庫中,主流的用的Git或者gitlab,提交完程式碼通過CI/CD平臺需要對程式碼進行拉取、編譯、構建,產生一個War包,然後交給Ansible然後傳送到雲主機上/物理機,然後通過負載均衡將專案暴露出去,然後會有資料庫,監控系統,日誌系統來提供相關的服務。
首先也是開發將程式碼放在程式碼倉庫,然後通過jenkins去完成拉取程式碼,編譯,上傳到我們的映象倉庫。
這裡是將程式碼打包成一個映象,而不是刻意執行的war或者jar包,這個映象包含了你的專案的執行環境和專案程式碼,這個映象可以放在任何docker上去run起來,都可以去訪問,首先得保證能夠在docker上去部署起來,再部署到k8s上,打出來的映象去放在映象倉庫中,來集中的去管理這些映象。
因為每天會產生幾十個或者上百個映象,必須通過映象倉庫去管理,這裡可能會去寫一個指令碼去連線k8smaster,而k8s會根據自己的部署去排程這些pod,然後通過ingress去釋出我們的應用,讓使用者去訪問,每個ingress會關聯一組pod,而service會建立這組pod的負載均衡,通過service去區分這些節點上的Pod。
然後資料庫是放在叢集之外,監控系統日誌系統也可以放在k8s叢集放在去部署,也可以放在之外,我們是放在k8s叢集內的,也不是特別敏感,主要用來運維和開發除錯用的,不會影響到我們的業務,所以我們優先去k8s中去部署。
現在以部署一個JAVA專案到我們的k8s中
一、安裝一個openjdk
[root@k8s-master ~]# yum -y install java-1.8.0-openjdk.x86_64 maven
[root@k8s-master ~]# java -version
openjdk version "1.8.0_222"
OpenJDK Runtime Environment (build 1.8.0_222-b10)
OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode)
然後我們將程式碼拉到本地一般Dockerfile中跟我們的程式碼都放在同一目錄下,
[root@k8s-master tomcat-java-demo-master]# ls
db Dockerfile LICENSE pom.xml README.md src
[root@k8s-master tomcat-java-demo-master]# vim Dockerfile
FROM lizhenliang/tomcat
LABEL maintainer zhaochengcheng
RUN rm -rf /usr/local/tomcat/webapps/*
ADD target/*.war /usr/local/tomcat/webapps/ROOT.war
二、進行編譯
這裡我們需要配置maven的國內源,這樣的話就比較快一點
[root@k8s-master CI]# vim /etc/maven/settings.xml
<mirror>
<id>central</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
[root@k8s-master tomcat-java-demo-master]# mvn clean package -D maven test.skip=true
[root@k8s-master tomcat-java-demo-master]# ls
db Dockerfile LICENSE pom.xml README.md src target
[root@k8s-master tomcat-java-demo-master]# cd target/
[root@k8s-master target]# ls
classes generated-sources ly-simple-tomcat-0.0.1-SNAPSHOT ly-simple-tomcat-0.0.1-SNAPSHOT.war maven-archiver maven-status
[root@k8s-master tomcat-java-demo-master]# cd target/
我們就使用這個編譯好的war包,然後打成映象,上傳到我們的Harbor倉庫裡
[root@k8s-master target]# ls
classes ly-simple-tomcat-0.0.1-SNAPSHOT maven-archiver
generated-sources ly-simple-tomcat-0.0.1-SNAPSHOT.war maven-status
[root@k8s-master tomcat-java-demo-master]# docker build -t 192.168.30.24/library/java-demo:latest .
三、上傳到映象倉庫
[root@k8s-master tomcat-java-demo-master]# docker login 192.168.30.24
Username: admin
Password:
Error response from daemon: Get https://192.168.30.24/v2/: dial tcp 192.168.30.24:443: connect: connection refused
這裡報錯,其實我們需要在每臺docker下都要寫入對harbor倉庫的信任才可以,後面上傳映象也會用
[root@k8s-master java-demo]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["http://f1361db2.m.daocloud.io"],
"insecure-registries": ["192.168.30.24"]
}
再等錄一下push就可以了
[root@k8s-master tomcat-java-demo-master]# docker push 192.168.30.24/library/java-demo:latest
四、控制器管理pod
編寫deployment,一般專案都寫到自定義的名稱空間下,名稱寫專案名稱,方便記憶,name: tomcat-java-demo
namespace: test
另外就是下一個專案名稱,這裡分為多個,一般有很多的元件組成,所以下面可以寫個app的名稱,比如元件1、2、3,起碼標籤有這兩個維度
project: www
app: java-demo
另外就是映象拉取,在哪個倉庫去下載,這裡我建議映象倉庫的專案名稱和我們定義的是一種,避免混了。我重新打個標籤,並傳到我們的私有映象倉庫中
[root@k8s-master java-demo]# docker tag 192.168.30.24/library/java-demo 192.168.30.24/tomcat-java-demo/java-demo
[root@k8s-master java-demo]# docker push 192.168.30.24/tomcat-java-demo/java-demo:latest
映象地址也改一下地址
imagePullSecrets:
- name: registry-pull-secret
containers:
- name: tomcat
image: 192.168.30.24/tomcat-java-demo/java-demo:latest
現在開始建立 yaml
建立專案的名稱空間
[root@k8s-master java-demo]# vim namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: test
[root@k8s-master java-demo]# kubectl create -f namespace.yaml
namespace/test created
[root@k8s-master java-demo]# kubectl get ns
NAME STATUS AGE
default Active 22h
kube-node-lease Active 22h
kube-public Active 22h
kube-system Active 22h
test Active 5s
建立一個secret來保證我們harbor映象倉庫的認證資訊,這裡一定要寫上我們的專案的名稱空間。
[root@k8s-master java-demo]# kubectl create secret docker-registry registry-pull-secret --docker-username=admin --docker-password=Harbor12345 [email protected] --docker-server=192.168.30.24 -n test
secret/registry-pull-secret created
[root@k8s-master java-demo]# kubectl get ns
NAME STATUS AGE
default Active 23h
kube-node-lease Active 23h
kube-public Active 23h
kube-system Active 23h
test Active 6m39s
[root@k8s-master java-demo]# kubectl get secret
NAME TYPE DATA AGE
default-token-2vtgm kubernetes.io/service-account-token 3 23h
registry-pull-secret kubernetes.io/dockerconfigjson 1 46s
[root@k8s-master java-demo]# vim deployment.yaml
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: tomcat-java-demo
namespace: test
spec:
replicas: 3
selector:
matchLabels:
project: www
app: java-demo
template:
metadata:
labels:
project: www
app: java-demo
spec:
imagePullSecrets:
- name: registry-pull-secret
containers:
- name: tomcat
image: 192.168.30.24/tomcat-java-demo/java-demo:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
name: web
protocol: TCP
resources:
requests:
cpu: 0.5
memory: 1Gi
limits:
cpu: 1
memory: 2Gi
livenessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 20
readinessProbe:
httpGet:
path: /
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 20
[root@k8s-master java-demo]# kubectl get pod -n test
NAME READY STATUS RESTARTS AGE
tomcat-java-demo-6d798c6996-fjjvk 1/1 Running 0 2m58s
tomcat-java-demo-6d798c6996-lbklf 1/1 Running 0 2m58s
tomcat-java-demo-6d798c6996-strth 1/1 Running 0 2m58s
另外就是暴露一個Service,這裡的標籤也要保持一致,不然他找不到相應的標籤就提供不了服務,這裡我們是使用ingress來訪問釋出應該,直接使用ClusterIP就可以
[root@k8s-master java-demo]# vim service.yaml
apiVersion: v1
kind: Service
metadata:
name: tomcat-java-demo
namespace: test
spec:
selector:
project: www
app: java-demo
ports:
- name: web
port: 80
targetPort: 8080
[root@k8s-master java-demo]# kubectl get pod,svc -n test
NAME READY STATUS RESTARTS AGE
pod/tomcat-java-demo-6d798c6996-fjjvk 1/1 Running 0 37m
pod/tomcat-java-demo-6d798c6996-lbklf 1/1 Running 0 37m
pod/tomcat-java-demo-6d798c6996-strth 1/1 Running 0 37m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/tomcat-java-demo ClusterIP 10.1.175.191 <none> 80/TCP 19s
測試訪問我們的專案,是可以的,現在要釋出出去通過ingress
[root@k8s-master java-demo]# curl 10.1.175.191
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>把美女帶回家應用案例</title>
<meta name="description" content="把美女帶回家應用案例">
<meta name="keywords" content="index">
現在部署一個ingress-nginx的控制器,這個網上都可以找到,官方也有,我這裡是按DaemonSet的方式去部署的,所以每個節點都會跑一個控制器。
[root@k8s-master java-demo]# kubectl get pod -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-g95pp 1/1 Running 0 3m6s
nginx-ingress-controller-wq6l6 1/1 Running 0 3m6s
釋出應用
這裡注意兩點,第一個就是網站域名,一個是service的名稱空間。
[root@k8s-master java-demo]# kubectl get pod,svc -n test
NAME READY STATUS RESTARTS AGE
pod/tomcat-java-demo-6d798c6996-fjjvk 1/1 Running 0 53m
pod/tomcat-java-demo-6d798c6996-lbklf 1/1 Running 0 53m
pod/tomcat-java-demo-6d798c6996-strth 1/1 Running 0 53m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/tomcat-java-demo ClusterIP 10.1.175.191 <none> 80/TCP 16m
[root@k8s-master java-demo]# vim service.yaml
[root@k8s-master java-demo]# kubectl create -f ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: tomcat-java-demo
namespace: test
spec:
rules:
- host: java.maidikebi.com
http:
paths:
- path: /
backend:
serviceName: tomcat-java-demo
servicePort: 80
另外我這邊是測試的,所以繫結我本地的hosts來進行訪問,在hosts檔案裡面加入域名和和節點ip就能訪問到我們的專案了。