javascript
Spring Cloud Kubernetes容器化实践
隨著公司業(yè)務(wù)量和產(chǎn)品線的增加,項目越來越多,普通運維系統(tǒng)架構(gòu)對整個軟件研發(fā)生命周期的管理越來越難,效率低下,難以統(tǒng)一管理。近年來Docker統(tǒng)一了容器標(biāo)準(zhǔn),對于軟件開發(fā)流程產(chǎn)生了深遠(yuǎn)的影響,Docker可以一次打包,處處運行。過去幾年Kubernetes平臺發(fā)展日新月益,Kubernetes統(tǒng)一了容器編排王者的地位,我個人認(rèn)為kubernetes可以說是對普通運維架構(gòu)一次突破性的革命。
利用Kubernetes集群平臺可以很方便的對容器服務(wù)進(jìn)行集中管理,可以非常高效的對容器服務(wù)進(jìn)行編排、調(diào)度、擴容、升級、回滾、監(jiān)控、集中收集日志等,基本上把傳統(tǒng)運維架構(gòu)需要考慮的問題全部解決了,而DevOps容器化也是整個軟件開發(fā)流程的必經(jīng)之路,因此我們對現(xiàn)有老舊的運維平臺進(jìn)行替換,統(tǒng)一利用Kubernetes對所有業(yè)務(wù)進(jìn)行管理。
?
原有運維系統(tǒng)缺點
-
原有業(yè)務(wù)布署在虛擬機ECS、KVM上,腳本分散、日志分散、難于集中收集管理,監(jiān)控不統(tǒng)一,CPU、內(nèi)存、磁盤資源使用率低,運維效率極低,無法集中管理。
-
新業(yè)務(wù)布署需要開通新的虛擬機,需要單獨定制監(jiān)控,各種Crontab,配置腳本,效率低下,CI/CD Jenkins配置繁瑣。
?
Kubernetes容器化優(yōu)勢
-
利用Kubernetes容器平臺namespaces對不同環(huán)境進(jìn)行區(qū)分,建立不同dev、test、stage、prod環(huán)境,實現(xiàn)隔離。
-
通過容器化集中布署所有業(yè)務(wù),實現(xiàn)一鍵布署所需環(huán)境業(yè)務(wù)。
-
統(tǒng)一集中監(jiān)控報警所有容器服務(wù)異常狀態(tài)。
-
統(tǒng)一集中收集所有服務(wù)日志至ELK集群,利用Kibana面板進(jìn)行分類,方便開發(fā)查日志。
-
基于Kubernetes命令行二次開發(fā),相關(guān)開發(fā)、測試人員直接操作容器。
-
基于RBAC對不同的環(huán)境授于不同的開發(fā)、測試訪問Kubernetes權(quán)限,防止越權(quán)。
-
通過Jenkins統(tǒng)一CI/CD編譯發(fā)布過程。
-
項目容器化后,整體服務(wù)器CPU、內(nèi)存、磁盤、資源利用減少50%,運維效率提高60%,原來需要N個運維做的事,現(xiàn)在一個人即可搞定。
?
Kubernetes本身是一套分布式系統(tǒng),要用好會遇到很多問題,不是說三天兩頭就能搞定,需要具備網(wǎng)絡(luò)、Linux系統(tǒng)、存儲,等各方面專業(yè)知識,在使用過程中我們也踩了不少坑,我們是基于二進(jìn)制包的方式安裝Kubernetes集群,我們Kubernetes集群版本為1.10,經(jīng)過一段時間的實踐,Kubernetes對于我們整個開發(fā)、測試、發(fā)布、運維流程幫助非常大,值得大力推廣。
?
網(wǎng)絡(luò)方案選擇
Flannel是 CoreOS 團隊針對 Kubernetes 設(shè)計的一個覆蓋網(wǎng)絡(luò)(Overlay Network)工具,所有節(jié)點通過flanneld節(jié)點服務(wù)同步路由,使用簡單、方便、穩(wěn)定,是Kubernetes入門首選。
Calico是基于BGP協(xié)議的路由方案,支持ACL,部署復(fù)雜,出現(xiàn)問題難排查。
Weave是基于UDP承載容器之間的數(shù)據(jù)包,并且可以完全自定義整個集群的網(wǎng)絡(luò)拓?fù)?#xff0c;國內(nèi)使用較少。
Open vSwitch是一個生產(chǎn)質(zhì)量的多層虛擬交換機,它旨在通過編程擴展實現(xiàn)大規(guī)模網(wǎng)絡(luò)自動化,同時仍支持標(biāo)準(zhǔn)管理接口和協(xié)議,OpenShift-kubernetes平臺和混合云使用比較多。
我們對各個網(wǎng)絡(luò)組件進(jìn)行過調(diào)研對比,網(wǎng)絡(luò)方案選擇的是flanneld-hostgw+ipvs,在Kubernetes 1.9之前是不支持IPVS的,kube-proxy負(fù)責(zé)所有SVC規(guī)則的同步,使用的iptables,一個service會產(chǎn)生N條iptables記錄。如果SVC增加到上萬條,iptables-svc同步會很慢,得幾分鐘,使用IPVS之后,所有節(jié)點的SVC由IPVS LVS來負(fù)載,更快、更穩(wěn)定,而且簡單方便,使用門檻低。host-gw會在所有節(jié)點同步路由表,每個容器都分配了一個IP地址,可用于與同一主機上的其他容器進(jìn)行通信。對于通過網(wǎng)絡(luò)進(jìn)行通信,容器與主機的IP地址綁定。flanneld host-gw性能接近Calico,相對來說Falnneld配置布署比Calico簡單很多。順便提下flanneld-vxlan這種方式,需要通過UDP封包解包,效率較低,適用于一些私有云對網(wǎng)絡(luò)封包有限制,禁止路由表添加等有限制的平臺。
Flanneld通過為每個容器提供可用于容器到容器通信的IP來解決問題。它使用數(shù)據(jù)包封裝來創(chuàng)建跨越整個群集的虛擬覆蓋網(wǎng)絡(luò)。更具體地說,Flanneld為每個主機提供一個IP子網(wǎng)(默認(rèn)為/ 24),Docker守護程序可以從中為每個主機分配IP。
Flannel使用etcd來存儲虛擬IP和主機地址之間的映射。一個Flanneld守護進(jìn)程在每臺主機上運行,并負(fù)責(zé)維護etcd信息和路由數(shù)據(jù)包。
在此提一下,在使用flannled過程中遇到過嚴(yán)重bug,即租約失效,flanneld會shutdown節(jié)點網(wǎng)絡(luò)組件,節(jié)點網(wǎng)絡(luò)直接崩掉,解決辦法是設(shè)置永久租期:https://coreos.com/flannel/docs/latest/reservations.html#reservations。
?
傳統(tǒng)業(yè)務(wù)遷移至Kubernetes遇到的問題和痛點,DevOps遇到的問題
使用Kubernetes會建立兩套網(wǎng)絡(luò),服務(wù)之間調(diào)用通過service域名,默認(rèn)網(wǎng)絡(luò)、域名和現(xiàn)有物理網(wǎng)絡(luò)是隔離的,開發(fā),測試,運維無法像以前一樣使用虛擬機,Postman IP+端口調(diào)試服務(wù), 網(wǎng)絡(luò)都不通,這些都是問題。
-
Pod網(wǎng)絡(luò)和物理網(wǎng)絡(luò)不通,Windows辦公電腦、Linux虛擬機上現(xiàn)有的業(yè)務(wù)和Kubernetes是隔離的。
-
SVC網(wǎng)絡(luò)和物理網(wǎng)絡(luò)不通,Windows辦公電腦、Linux虛擬機上現(xiàn)有的業(yè)務(wù)和Kubernetes是隔離的。
-
SVC域名和物理網(wǎng)絡(luò)不通,Windows辦公電腦、Linux虛擬機上現(xiàn)有的業(yè)務(wù)和Kubernetes是隔離的。
-
原有Nginx配置太多的location路由規(guī)則,有的有幾百層,不好遷移到ingress-nginx,ingress只支持簡單的規(guī)則。
-
SVC-NodePort訪問,在所有Node上開啟端口監(jiān)聽,占用Node節(jié)點端口資源,需要記住端口號。
-
ingress-nginx http 80端口, 必需通過域名引入,原來簡單nginx的location可以通過ingress引入。
-
ingress-nginx tcp udp端口訪問需要配置一個lb,很麻煩,要先規(guī)劃好lb節(jié)點同樣也需要訪問lb端口。
-
原有業(yè)務(wù)不能停,繼續(xù)運行,同時要能兼容Kubernetes環(huán)境,和Kubernetes集群內(nèi)服務(wù)互相通訊調(diào)用,網(wǎng)絡(luò)需要通。
傳統(tǒng)虛擬機上布署服務(wù)我們只需要一個地址+端口直接訪問調(diào)試各種服務(wù),Kubernetes是否能做到不用改變用戶使用習(xí)慣,無感知使用呢?答案是打通DevOps全鏈路,像虛擬機一樣訪問Kubernetes集群服務(wù) , 我們打通Kubernetes網(wǎng)絡(luò)和物理網(wǎng)絡(luò)直通,物理網(wǎng)絡(luò)的DNS域名調(diào)用Kubernetes DNS域名服務(wù)直接互訪,所有服務(wù)互通。公司原有業(yè)務(wù)和現(xiàn)有Kubernetes集群無障礙互訪。
配置一臺Kubernetes Node節(jié)點機做路由轉(zhuǎn)發(fā),配置不需要太高,布署成路由器模式,所有外部訪問Kubernetes集群流量都經(jīng)該節(jié)點,本機IP:192.168.2.71。
vim /etc/sysctl.conf net.ipv4.ip_forward = 1設(shè)置全網(wǎng)路由通告,交換機或者Linux、Windows主機加上靜態(tài)路由,打通網(wǎng)絡(luò)。
route add -net 172.20.0.0 netmask 255.255.0.0 gw 192.168.2.71 route add -net 172.21.0.0 netmask 255.255.0.0 gw 192.168.2.71增加DNS服務(wù)器代理,外部服務(wù)需要訪問Kubernetes service域名,首先需要解析域名,Kubernetes服務(wù)只對集群內(nèi)部開放,此時需要外部能調(diào)用KubeDNS 53號端口,所有辦公電腦,業(yè)務(wù)都來請求KubeDNS肯定撐不住,事實上確實是撐不住,我們做過測試,此時需要配置不同的域名進(jìn)行分流策略,公網(wǎng)域名走公網(wǎng)DNS,內(nèi)部.svc.cluster.local走KubeDNS。
1、建立DNS代理服務(wù)器,ingress建立一個nginx-ingress服務(wù)反代KubeDNS,ingress-nginx綁定到DNS節(jié)點運行,在節(jié)點上監(jiān)聽DNS 53端口。
[root@master1 kube-dns-proxy-1.10]# cat tcp-services-configmap.yaml kind: ConfigMap apiVersion: v1 metadata:name: tcp-servicesnamespace: ingress-nginx data:53: "kube-system/kube-dns:53"[root@master1 kube-dns-proxy-1.10]# cat udp-services-configmap.yaml kind: ConfigMap apiVersion: v1 metadata:name: udp-servicesnamespace: ingress-nginx data:53: "kube-system/kube-dns:53"[root@master1 kube-dns-proxy-1.10]# cat ingress-nginx-deploy.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata:name: nginx-ingress-controller-dnsnamespace: ingress-nginx spec:replicas: 1selector:matchLabels:app: ingress-nginx-dnstemplate:metadata:labels:app: ingress-nginx-dnsannotations:prometheus.io/port: '10254'prometheus.io/scrape: 'true'spec:hostNetwork: trueserviceAccountName: nginx-ingress-serviceaccountcontainers:- name: nginx-ingress-controller-dnsimage: registry-k8s.novalocal/public/nginx-ingress-controller:0.12.0args:- /nginx-ingress-controller- --default-backend-service=$(POD_NAMESPACE)/default-http-backend# - --configmap=$(POD_NAMESPACE)/nginx-configuration- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services- --udp-services-configmap=$(POD_NAMESPACE)/udp-services- --annotations-prefix=nginx.ingress.kubernetes.ioenv:- name: POD_NAMEvalueFrom:fieldRef:fieldPath: metadata.name- name: POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespaceports:- name: httpcontainerPort: 80#- name: https# ?containerPort: 443livenessProbe:failureThreshold: 3httpGet:path: /healthzport: 10254scheme: HTTPinitialDelaySeconds: 10periodSeconds: 10successThreshold: 1timeoutSeconds: 1readinessProbe:failureThreshold: 3httpGet:path: /healthzport: 10254scheme: HTTPperiodSeconds: 10successThreshold: 1timeoutSeconds: 1nodeSelector:node: dns2、最簡單快捷的方式是安裝Dnsmasq,當(dāng)然你也可以用Bind,PowerDNS,CoreDNS等改造,上游DNS配置為上一步驟增加nginx-ingress dns的地址,所有辦公,業(yè)務(wù)電腦全部設(shè)置DNS為此機,dnsmasq.conf配置分流策略。
no-resolv server=/local/192.168.1.97 server=114.114.114.114完成以上步驟后,Kubernetes pod網(wǎng)絡(luò)、service網(wǎng)絡(luò)、 service域名和辦公網(wǎng)絡(luò),現(xiàn)有ECS、虛擬機完美融合,無縫訪問,容器網(wǎng)絡(luò)問題完美搞定。
?
Windows訪問Kubernetes service暢通無組,開發(fā)測試,完美無縫對接。
?
ingress-nginx服務(wù)入口接入
服務(wù)發(fā)布后最終對接的是用戶,用戶訪問Kubernetes服務(wù)需要通過nginx或其它http服務(wù)器接入,對于服務(wù)接入我們同時使用兩種不同的方案,取決于nginx location的復(fù)雜度,location規(guī)則簡單的我們使用第一種方案,由于各種問題,location復(fù)雜我們使用第二種方案。
client-------ingress-nginx-----upstream----podip,對于ingress-nginx官方使用的原始方案,先配置ingress規(guī)則路由,ingress對接不同的service-dns域名,ingress自動發(fā)現(xiàn)后端podip,通過upstream負(fù)載不同的后端podip,不同的域名路由到不同的Kubernetes后端podip,用戶客戶端訪問流量會負(fù)載到不同的Pod上。
client------nginx-------upstream------svc-----podip改造現(xiàn)有nginx兼容Kubernetes,對接Kubernetes service服務(wù)。對于nginx location規(guī)則過多,不能很好的兼容nginx-ingress導(dǎo)致使用Kubernetes非常困難,難以普及,在不變更現(xiàn)有nginx配置的情況下如何對接Kubernetes這是一個問題,經(jīng)過前面網(wǎng)絡(luò)打通的步驟我們所有網(wǎng)絡(luò)的問題都已解決。現(xiàn)在只需改動很小部分即可兼容,由于Kubernetes pod ip是漂移的,IP總是會變的,nginx只能是對接SVC域名才能持久,但是nginx解析域名有個bug,只解析一次,如果在此期間刪除了yaml,nginx會找不到后端svcip,所以這里要設(shè)置代理變量set $backend,設(shè)置resolver的DNS為代理DNS地址,設(shè)置解析域名時間和變量解決該問題。
大家可能擔(dān)心Eureka和Kubernetes service有沖突,Spring Cloud本身自帶服務(wù)發(fā)現(xiàn)Eureka,組件之間的調(diào)用通過Eureka注冊調(diào)用,其實你直接布署就行了,Eureka和Service沒任何沖突,和普通Java應(yīng)用一樣用。
?
監(jiān)控方案
目前使用的Kubernetes官方的Heapster,Monitoring-InfluxDB-Grafana +自定議腳本+自定義Grafana面板可以靈活報警。
監(jiān)控面板按業(yè)務(wù)環(huán)境dev/test/stage/prod/對CPU/內(nèi)存/網(wǎng)絡(luò)等分類進(jìn)行展示。
節(jié)點資源監(jiān)控:?
Pod CPU、內(nèi)存、網(wǎng)絡(luò)等監(jiān)控:?
監(jiān)控腳本,可以很靈活跟據(jù)設(shè)定參數(shù)進(jìn)行釘釘報警,報告有問題的Pod、Node,自動處理有問題的服務(wù)。
#!/bin/bash #最大內(nèi)存排除的node節(jié)點 exclude_node="node7|node1|node2|node3|master1" exclude_pod="redis|kafka|mongo|zookeeper|Evicted|Completed" #node使用的最大報警內(nèi)存%比 node_mem_max="100" #node最大使用cpu百分比 node_cpu_max="80" #pod使用的最大報警內(nèi)存MB pod_mem_max="4096" pod_top="5" pod_top_cpu="10" #pod的啟動錯誤時間,單位為秒s pod_error_m_time="120" pyding="$HOME/k8s-dev/dingd-zabbix.python" #pod的內(nèi)存以及cpu的使用狀態(tài) pod_mem=$(/usr/local/bin/kubectl top pod --all-namespaces ?|sort -n -k4 ) #node的內(nèi)存使用狀態(tài) node_status=$(/usr/local/bin/kubectl top node|egrep -v "${exclude_node}" |egrep -v "MEMORY%") #pod的運行狀態(tài) pod_status=$(/usr/local/bin/kubectl get pod --all-namespaces -o wide|grep -v NAMESPACE) #設(shè)定有問題的pod存取文件路徑 alert_error_pod="/tmp/alert-error-pod.txt" #設(shè)定最大內(nèi)存占用節(jié)點上pod的文件列表路徑 alert_list="/tmp/alert-mem-list.txt" #監(jiān)控cpu百分比文件輸出路徑 alert_node_cpu_list="/tmp/alert_node_cpu_list.txt" #取node內(nèi)存的百分比數(shù)字值 #node_pre_mem=$(echo "${node_mem}"|awk '{print $5}'|sed -e "s/%//g") #監(jiān)控node的內(nèi)存百分比,列出占用內(nèi)存最高的應(yīng)用并重啟top5應(yīng)用 node_mem_mon () {echo "${node_status}" |awk '{print $1,$5}'|sed -e "s/%//g" |while read node_name node_mem_status;do#echo $node_name $node_mem_statusif [ "${node_mem_status}" -gt "${node_mem_max}" ];then>${alert_list}#找到該節(jié)點上的所有的pod名find_pod=$(echo "${pod_status}"|egrep ${node_name}|awk '{print $2}')#找到所有節(jié)點倒排序使用最大的內(nèi)存的pod列表for i in $(echo "${find_pod}");doecho "${pod_mem}"|grep $i ?>>${alert_list}donedate_time=`date +'%F-%T'`echo -e "\n${node_name}最大內(nèi)存超過 %${node_mem_max} 以下pod應(yīng)用將被重啟 ------------------\n"cat ${alert_list}|sort -n -k 4|tail -${pod_top}python ${pyding} ?"`echo -e "\n ${date_time} ${node_name}當(dāng)前內(nèi)存為${node_mem_status}%,最大內(nèi)存超過 %${node_mem_max} 以下pod應(yīng)用將被重啟 ------------------\n" ;cat ${alert_list}|sort -n -k 4|egrep -v "$exclude_pod"|tail -${pod_top}` "cat ${alert_list}|sort -n -k 4|egrep -v "$exclude_pod"|tail -${pod_top}|egrep -v "應(yīng)用將被重啟" | awk '{print ?"/usr/local/bin/kubectl delete pod ?"$2" -n "$1" " | "/bin/bash"}'fidone}?
釘釘報警圖:?
?
Kubernetes集群yaml容器編排管理
Kubernetes通過yaml對容器進(jìn)行管理,yaml配置編排文件是管理整個容器生命周期重要的一部份,管理好yaml非常重要。我開發(fā)了一套類似于Helm的模板的腳本框架,用于所有環(huán)境的yaml初始化工作 ,自己寫腳本的好處就是可以靈活控制,比如哪個組件要掛載存儲,共享卷,要配置私有hosts等,我可以一次性定制好,初始化時只需要init-yaml直接批量搞定,不需要每個yml單獨去修改,之后就是kubectl create 直接用。
容器編排yaml文件按空間環(huán)境dev、test、stage、prod進(jìn)行模板base分類,復(fù)制一套yaml模板即可生成其它各環(huán)境,容器編排按業(yè)務(wù)類型模塊配置conf app-list。
[root@master1 config]# lspublic-dev_app_list.conf ? ? ?public-test-base.yml ? ?public-dev-base.yml ? ? ? ? ? sms-test_app_list.conf ?public-pretest_app_list.conf ?sms-test-base.yml ? ? ? ?public-pretest-base.yml ? ? ? wbyh-dev_app_list.conf ?public-stage_app_list.conf ? ?wbyh-dev-base.yml ? ? ? ?public-stage-base.yml ? ? ? ? wbyh-stage_app_list.confpublic-test_app_list.conf ? ? wbyh-stage-base.yml通過Kubernetes核心排編腳本進(jìn)行init-yml初始化對應(yīng)環(huán)境,生成所有Pod的yaml排編文件,每套環(huán)境可以生成環(huán)境對應(yīng)的MySQL、Redis、Kafka、MongoDB等,直接啟動即可調(diào)用。
[root@master1 k8s-dev]# ./k8s wbyh-stage init-yml /root/k8s-dev/config [root@master1 k8s-dev]# tree wbyh-stage/ ├── app │ ? ├── dac-api-center │ ? │ ? └── dac-api-center.yml │ ? ├── dac-app-web │ ? │ ? └── dac-app-web.yml │ ? ├── dac-config-server │ ? │ ? └── dac-config-server.yml │ ? ├── dac-eureka-server │ ? │ ? └── dac-eureka-server.yml │ ? ├── dac-task │ ? │ ? └── dac-task.yml │ ? ├── dac-task-apply │ ? │ ? └── dac-task-apply.yml │ ? ├── dac-task-h5 │ ? │ ? └── dac-task-h5.yml │ ? ├── dac-web │ ? │ ? └── dac-web.yml │ ? ├── dac-message-center │ ? │ ? └── dac-message-center.yml │ ? ├── dac-quartz-jfdata │ ? │ ? └── dac-quartz-jfdata.yml │ ? ├── dac-quartz-mach │ ? │ ? └── dac-quartz-mach.yml │ ? ├── dac-quartz-dac │ ? │ ? └── dac-quartz-dac.yml │ ? ├── dac-resources-center │ ? │ ? └── dac-resources-center.yml │ ? ├── dac-resources-item │ ? │ ? └── dac-resources-item.yml │ ? ├── dac-usercenter-web │ ? │ ? └── dac-usercenter-web.yml │ ? └── tomcat │ ? ? ? └── tomcat.yml └── stateful-sets├── kafka│ ? ├── 10kafka-config-0420yml│ ? ├── 10kafka-config.yml│ ? ├── 20dns.yml│ ? └── 50kafka.yml├── mongo│ ? └── mongo-statefulset.yml├── redis│ ? ├── primary.yml│ ? └── redis-configmap.yml└── zookeeper├── 10zookeeper-config.yml├── 30service.yml└── 50pzoo.yml22 directories, 26 files通過Kubernetes腳本調(diào)用kubectl可以直接批量創(chuàng)建該空間下所有服務(wù)。
[root@master1 k8s-dev]# ./k8s wbyh-stage create_all /root/k8s-dev/config configmap "dac-eureka-server-filebeat-config" created service "dac-eureka-server" created deployment.extensions "dac-eureka-server" created configmap "dac-config-server-filebeat-config" created service "dac-config-server" created deployment.extensions "dac-config-server" created configmap "tomcat-filebeat-config" created service "tomcat" created deployment.extensions "tomcat" created所有代碼存入GitLab做版本管理,即基礎(chǔ)設(shè)施即代碼。
add svn-jar-version ll itemcommit 29dc05530d839c826130eef81541ce96a155107b Author: idea77 <idea77@qq.com> Date: ? Thu Sep 20 16:11:00 2018 +0800mod ossfs to /Rollback/osscommit 880bcd9483a6ee1f5ca440fef017b30ba7cd14fe Author: idea77 <idea77@qq.com> Date: ? Wed Sep 19 16:57:43 2018 +0800?
存儲方案
目前公司一部份應(yīng)用掛載的卷為NFS,讀寫要求不高的可以配置NFS, 一部份要求比較高的用的Ceph,如MySQL、Kafka之類的就需要Ceph支撐,對于需要持久化的DB類型存儲的管理用StorageClass存儲類對接管理,很方便自動建立存儲卷PV-PVC對接,共享卷類型可以直接掛載卷。
NFS配置需要在每個Node節(jié)點安裝NFS-Utils,配置yml,注意CentOS 7低版本3.10內(nèi)核的nfs-server有bug,導(dǎo)致服務(wù)器重啟,升到4.0以上內(nèi)核解決問題。
?- name: tomcat-imgnfs:path: /home/k8s-nfs-data/dac-test-tomcat-imgserver: 192.168.8.30Ceph Kubernetes Node節(jié)點安裝ceph-commo,配置StorageClass。
ceph-class.yaml apiVersion: storage.k8s.io/v1beta1 kind: StorageClass metadata:name: ceph-db provisioner: kubernetes.io/rbd parameters:monitors: 192.168.1.31:6789adminId: adminadminSecretName: ceph-secretadminSecretNamespace: kube-systempool: rbduserId: adminuserSecretName: ceph-secret?
Jenkins CI/CD編譯發(fā)布階段
Jenkins CI/CD控制臺完成整個jar包編譯,Dockerfile編譯、docker push、Kubernetes deployment鏡像滾動升級功能。
Jenkins Manage and Assign Roles授權(quán)不同的開發(fā)、測試組不同的用戶權(quán)限,隔離不同的項目編譯發(fā)布權(quán)限。?
目前沒有完全用上流水線服務(wù),完全流水線需要構(gòu)建不報錯,一報錯也就無法完成,不是很靈活,構(gòu)建jar包和發(fā)布docker-image是分開的,需要跟據(jù)公司業(yè)務(wù)來。
編譯階段我們做了釘釘通知,每個項目拉了自己的群,編譯jar包是否成功整個組都有通知,同樣update發(fā)布是否成功都有提示,群內(nèi)可見。?
目前我們Kubernetes容器啟動分為兩種架構(gòu):
容器發(fā)布后啟動基礎(chǔ)JDK鏡像,Wget去http服務(wù)器下載對應(yīng)目錄編譯好的jar包,然后啟動,即無鏡像模式,適合頻繁發(fā)布類型的業(yè)務(wù),push jar to oss有一部份業(yè)務(wù)是跑虛擬機,需要jar包,oss可以做共享。
容器發(fā)布按照標(biāo)準(zhǔn)的方式打image update-image模式,適合出錯及時回滾的業(yè)務(wù),即編譯dockerfile-push-docker-image-update-deployment。
build-$namespace通過空間變量名擬寫對應(yīng)腳本,基本是做一個通用模板base,復(fù)制生成對應(yīng)項目的build.sh供Jenkins傳參調(diào)用,每套環(huán)境有自己的基礎(chǔ)鏡像base,基礎(chǔ)鏡像就是打入JDK等一些私有的配置,編譯的時候在基礎(chǔ)鏡像上加上jar包。
if [[ $MY_POD_NAMESPACE =~ -dev ]];then#定義啟動基礎(chǔ)鏡相base_image="registry-k8s.novalocal/public/yh-centos7-jdk-1.8"#定義APP鏡像倉庫地址image_path="registry-k8s.novalocal/xl_public/$MY_POD_NAMESPACE/${APP}" elif [[ $MY_POD_NAMESPACE =~ "-test" ]];then#定義啟動基礎(chǔ)鏡相base_image="registry-k8s.novalocal/public/yh-centos7-jdk-1.8"#定義APP鏡像倉庫地址image_path="registry-k8s.novalocal/xl_public/$MY_POD_NAMESPACE/${APP}:${date_time}" elif [[ $MY_POD_NAMESPACE =~ -stage ]];then#定義啟動基礎(chǔ)鏡相base_image="registry-k8s.novalocal/xl_public/wbyh-base/centos7-jdk-1.8"#定義idc鏡相倉庫路徑image_path="registry.cn-hangzhou-idc.com/xl_dac/wbyh-stage-${APP}:${date_time}"vpc_image_path="registry-vpc.cn-hangzhou-idc.com/wbyh-stage-${APP}:${date_time}" fi#初始化dockerfileinit_dockerfile () {#生成Dockerfilecd /Rollback/build-docker/echo "" >$MY_POD_NAMESPACE/${APP}/Dockerfile#生成基礎(chǔ)鏡像地址echo -e "${base_image}" ?>>${MY_POD_NAMESPACE}/${APP}/Dockerfile#生成docker作者echo -e "MAINTAINER idea77@qq.com" >>${MY_POD_NAMESPACE}/${APP}/Dockerfileecho -e "USER root" ?>>${MY_POD_NAMESPACE}/${APP}/Dockerfile#獲取啟動腳本\cp -f ?start-sh/${MY_POD_NAMESPACE}-sh/${APP}.sh ?$MY_POD_NAMESPACE/${APP}/echo -e "ADD ./${APP}.sh /home/deploy/" >>${MY_POD_NAMESPACE}/${APP}/Dockerfile#添加 jar包到/home/deploy/echo -e "${add_jar}" >>${MY_POD_NAMESPACE}/${APP}/Dockerfile#暴露端口echo -e "EXPOSE 9090" ?>>${MY_POD_NAMESPACE}/${APP}/Dockerfile#添加docker入口啟動文件\cp -f ?start-sh/templates/docker-entrypoint.sh $MY_POD_NAMESPACE/${APP}/echo -e "ADD ./docker-entrypoint.sh ?/docker-entrypoint.sh" >>$MY_POD_NAMESPACE/$APP/Dockerfileecho -e "RUN ?chown -R deploy:deploy /home/deploy && ?chown -R deploy:deploy /docker-entrypoint.sh && ls -t --full /home/deploy " >>$MY_POD_NAMESPACE/$APP/Dockerfileecho -e "USER deploy" ?>>$MY_POD_NAMESPACE/$APP/Dockerfileecho -e 'ENTRYPOINT ["/docker-entrypoint.sh"]' >>$MY_POD_NAMESPACE/$APP/Dockerfileif [[ ${MY_POD_NAMESPACE} =~ -prod ]];thendocker images |grep xl_prod|grep ${APP}|awk '{print $1":"$2}'|xargs docker rmi -felsedocker images |grep min-test|grep ${APP}|awk '{print $1":"$2}'|xargs docker rmi -ffiname="${MY_POD_NAMESPACE},build ${image_path}-${svn_version}"cd /Rollback/build-docker/$MY_POD_NAMESPACE/$APP/docker build ?--no-cache -t ${image_path}-${svn_version} .checkif [[ $MY_POD_NAMESPACE =~ -stage ?]];then#vpc專有鏡相地址修改到y(tǒng)ml文件sed -i "s@registry-vpc.cn-hangzhou-idc.com/xl_public\(.*\)@${vpc_image_path}-${svn_version}@g" ? ?/home/deploy/k8s-dev/${MY_POD_NAMESPACE}/app/$APP/$APP.ymlelif [[ $MY_POD_NAMESPACE =~ -test ?]];thensed -i "s@registry-k8s.novalocal/xl_public/\(.*\)@${image_path}-${svn_version}@g" ? ?/home/deploy/k8s-dev/${MY_POD_NAMESPACE}/app/$APP/$APP.ymlfiname="push ${APP}"docker push ?${image_path}-${svn_version}check }Jenkins觸發(fā):?
?
build-----push------updae-deployment-----image,整個過程是流水線形式,一次性連續(xù)完成,完成后通過機器人通知到各業(yè)務(wù)組,中間有任何問題,機器人會告訴我們在哪個階段出錯,很方便排查問題,鏡像的版本號根據(jù)Git或SVN的版本號來獲取,然后加上當(dāng)前時間戳,在jar包編譯階段版本號會寫入特定文件,Jenkins會跟據(jù)當(dāng)前編譯的版本生成對應(yīng)的Docker鏡像版本。?
?
?
Kubernetes日志方案
普通虛擬機日志分散,難管理,需要登陸虛擬機一個個查看,利用Kubernetes Pod多容器策略可以很方便幫我們收集管理日志,日志方案有幾種。
應(yīng)用打到docker stdout前臺輸出,Docker輸出到/var/lib/containers,通過Filebeat、Fluentd、DaemonSet組件收集,這種對于小量日志還可以,大量日志性能很差,寫入很慢。
Pod掛載host-path把日志打到宿主機,宿主機啟動Filebeat、Fluentd、DaemonSet收集,無法判斷來自哪個容器,哪個Pod和namespace空間。
Pod的yml中定義兩個container,同時啟動一個附加的Filebeat,兩個container掛載一個共享卷來收集日志。
我們用第三種方案,通過一個附加容器Filebeat來收集所有日志,filebeat–kafka–logstash–es,自定義編譯Filebeat容器鏡像,為Filebeat打上podip空間service名等標(biāo)簽,方便識別來自哪個容器,哪個namespace,配置config-map以及yaml。
filebeat----kafkacluster-----logstash----es apiVersion: v1 kind: ConfigMap metadata:namespace: dac-prodname: dac-config-server-filebeat-config data:filebeat.yml: |filebeat.prospectors:- input_type: logfields:namespace: dac-prodservice-name: dac-config-server#pod-ip:paths:- "/mnt/*.log"multiline:pattern: '^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3}'negate: truematch: after#output.elasticsearch:output.kafka:hosts: ["10.31.222.108:9092", "10.31.222.109:9092", "10.31.222.110:9092"]topic: applogrequired_acks: 1compression: gzip# Available log levels are: critical, error, warning, info, debuglogging.level: info --- apiVersion: v1 kind: Service metadata:name: dac-config-servernamespace: dac-prod spec:ports:- port: 9090name: httpselector:app: dac-config-server --- apiVersion: apps/v1 kind: Deployment metadata:name: dac-config-servernamespace: dac-prodlabels:app: dac-config-server spec:replicas: 1strategy:rollingUpdate:maxSurge: 1maxUnavailable: 1type: RollingUpdateselector:matchLabels:app: dac-config-servertemplate:metadata:labels:app: dac-config-serverspec:affinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- dac-config-servertopologyKey: "kubernetes.io/hostname"imagePullSecrets:- name: myregistrykeycontainers:- image: registry-vpc.cn-hangzhou-idc.com/dac-prod-dac-config-server:v1name: dac-config-serverimagePullPolicy: Alwaysresources:limits:cpu: 4000mmemory: 4096Mirequests:cpu: 150mmemory: 1024Mienv:- name: APPvalue: dac-config-server#public- name: JAVA_OPTSvalue: "-Xms4g -Xmx4g"- name: CONTAINER_CORE_LIMITvalue: "4"- name: POD_IPvalueFrom:fieldRef:fieldPath: status.podIP- name: MY_POD_NAMESPACEvalueFrom:fieldRef:fieldPath: metadata.namespacereadinessProbe:tcpSocket:port: 9090initialDelaySeconds: 60timeoutSeconds: 3livenessProbe:tcpSocket:port: 9090initialDelaySeconds: 60timeoutSeconds: 3ports:- name: httpcontainerPort: 9090volumeMounts:#- name: opt-data#mountPath: /home/deploy- name: logsmountPath: /home/deploy/logs- name: host-timemountPath: /etc/localtimereadOnly: true- image: registry-vpc.cn-hangzhou-idc.com/dac_prod/filebeat:6.0.0name: filebeatimagePullPolicy: Alwaysenv:- name: POD_IPvalueFrom:fieldRef:fieldPath: status.podIPvolumeMounts:- name: logsmountPath: /mnt- name: filebeat-confmountPath: /etc/filebeat- name: host-timemountPath: /etc/localtimereadOnly: truenodeSelector:node: publicvolumes:- name: logsemptyDir: {}- name: filebeat-confconfigMap:name: dac-config-server-filebeat-config#- name: opt-data#nfs:#path: /home/k8s-nfs-data/public-dev-base#server: 10.10.1.30- name: host-timehostPath:path: /etc/localtimeFilebeat收集日志打上關(guān)鍵字標(biāo)簽,namespace,svc,podip等。?
?
Kibana集中日志展示,建立Dashboard分類,用戶可以按namespce分類不同環(huán)境,過濾選擇查看不同模塊的應(yīng)用日志。?
?
RBAC+二次開發(fā)Kubernetes腳本
簡化kubectl 命令,提供給研發(fā)團隊使用。實際上這里功能和Jenkins以及Kibana上是重復(fù)的,但是必需考慮到所有團隊成員的使用感受,有人喜歡命令行,有人喜歡界面,簡單好用就夠。我打個比方,比如看日志,有人可能喜歡用命令行tail -f看日志,用grep過濾等,有人喜歡用Kibana看,那怎么辦?于是就有了兩種方案,喜歡用圖形界面用Jenkins或Kibana,想用命令可以用命令操作,滿足你一切需求。統(tǒng)一集中通過指定的機器提供給開發(fā)、測試、運維使用,方便調(diào)試、排障。通過統(tǒng)一的入口可以直接對容器進(jìn)行服務(wù)創(chuàng)建、擴容、重啟、登陸、查看日志、查看Java啟動參數(shù)等,方便整個團隊溝通。
?
在這里我們通過Kubernetes RBAC授權(quán)身份認(rèn)證,生成不同的證書configkey,授于不同項目組不同的管理權(quán)限,不同的項目組只有自己項目的權(quán)限。權(quán)限做了細(xì)分,不同研發(fā)、測試團隊互不干擾。?
[deploy@185 app]# k8s dac-test ?get_all NAME ? ? ? ? ? ? ? ? ? ? ? ? ?READY ? ? STATUS ? ?RESTARTS ? AGE ? ? ? IP ? ? ? ? ? ? NODE accountant-3536198527-dtrc9 ? 2/2 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.1.5 ? ? node3.k8s.novalocal analyzer-1843296997-vz9nc ? ? 2/2 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.87.15 ? node5.k8s.novalocal api-1260757537-gxrp2 ? ? ? ? ?2/2 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.71.6 ? ?k8s-monitor.novalocal calculator-1151720239-pr69x ? 2/2 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.1.12 ? ?node3.k8s.novalocal consul-0 ? ? ? ? ? ? ? ? ? ? ?1/1 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.87.3 ? ?node5.k8s.novalocal dispatcher-2608806384-kp433 ? 2/2 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.4.6 ? ? lb1.k8s.novalocal geo-1318383076-c7th2 ? ? ? ? ?2/2 ? ? ? Running ? 0 ? ? ? ? ?5m ? ? ? ?172.20.94.6 ? ?node6.k8s.novalocal greeter-79754259-s3bs2 ? ? ? ?2/2 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.19.5 ? ?jenkins-master.k8s.novalocal kafka-0 ? ? ? ? ? ? ? ? ? ? ? 1/1 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.1.4 ? ? node3.k8s.novalocal mqtt-0 ? ? ? ? ? ? ? ? ? ? ? ?1/1 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.94.15 ? node6.k8s.novalocal mysql-0 ? ? ? ? ? ? ? ? ? ? ? 2/2 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.47.7 ? ?elk-k8sdata.novalocal pusher-2834145138-lfs21 ? ? ? 2/2 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.19.6 ? ?jenkins-master.k8s.novalocal recovery-261893050-70s3w ? ? ?2/2 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.32.13 ? node4.k8s.novalocal redis-0 ? ? ? ? ? ? ? ? ? ? ? 1/1 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.4.5 ? ? lb1.k8s.novalocal robot-1929938921-6lz6f ? ? ? ?2/2 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.47.8 ? ?elk-k8sdata.novalocal scheduler-3437011440-rsnj6 ? ?2/2 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.5.10 ? ?db.k8s.novalocal valuation-2088176974-5kwbr ? ?2/2 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.94.20 ? node6.k8s.novalocal zookeeper-0 ? ? ? ? ? ? ? ? ? 1/1 ? ? ? Running ? 0 ? ? ? ? ?21h ? ? ? 172.20.4.4 ? ? lb1.k8s.novalocal 注意,如何操作用戶自己有權(quán)限的空間,必需填寫default-namespace.conf 注意,當(dāng)gitlab master分支有合并的時候,目前我們ci自動會構(gòu)建編譯最新的jar版本,推送至nexus倉庫,k8s容器里的jar包可以指定更新k8s ?init-yml ? ? ? ?#初始化生成用戶自己本人的yml文件 k8s ?get_all ? ? ? ? #查看用戶自己本人空間下的所有運行的容器 k8s ?create_all ? ? ?#創(chuàng)建用戶自己本人所有服務(wù) k8s ?delall_app ? ? ?#刪除本人空間下所有app服務(wù),除基礎(chǔ)服務(wù)mysql、 consul、 kafka、 redis、 zookeeper、mqtt 以外的所有服務(wù) k8s ?apply ?api ? ? ?#修改了用戶自己本人yml配置文件,應(yīng)用配置生效 k8s ?create api ? ? ?#用戶自己本人空間下創(chuàng)建一個api服務(wù) k8s ?delete api ? ? ?#用戶自己本人空間下刪除一個api服務(wù) k8s ?scale ?api 2 ? ?#用戶自己本人空間下把api服務(wù)擴容成2個pod k8s ?login ?api ? ? ?#用戶本人空間下登錄api所在的docker容器k8s ?logs ? api ? ? ?#用戶自己本人空間用tail -f 命令的方式查看容器內(nèi)/home/deploy/api/logs/api.log 的日志 k8s ?error-logs api ?#用戶自己本人空間用tail -f 命令的方式查看容器內(nèi)/home/deploy/api/logs/api.error.log 的日志 k8s ?clean api ? ? ? #如果編譯出錯,在用戶自己本人空間用gradlew clean清理命令的方式清理編譯 k8s ?push_jar ? ? ? ?#更新本人空間下所有容器的jar包版本,重啟所有容器,默認(rèn)拉取backend / push-envelope -git最終版本,該版本為合并編譯成功后的最新版本號 k8s ?push_jar ?20170927-1731 ? #選擇指定的jar版本號20170927-1731 進(jìn)行更新 ,重啟所有容器 k8s ?reinit-mysql ? ?#重新更新所有容器jar版本后api無法啟動,清空用戶空間下的數(shù)據(jù)庫,重新創(chuàng)建導(dǎo)入數(shù)據(jù)批量操作 k8s ?scale ?api-geo 2 #在dev用戶下把api和geo 擴容 k8s ?delete api-geo ? #在dev用戶下刪除api 和geo服務(wù) k8s ?create api-geo ? #在dev用戶下創(chuàng)建api和geo服務(wù)所有人員通用命令,要操作某個用戶的資源,必需先生成所需要的yml文件 但是必需指定第二個參數(shù)名dev test stage等。k8s stage init-yml ? ? ? #初始化生成stage用戶的yml文件 注意要操作stage用戶的容器要先成配置文件 k8s test init-yml ? ? ? ?#初始化生成test空間的yml文件 k8s dev init-yml ? ? ? ? #初始化生成dev空間的yml文件 k8s dev ?get_all ? ? ? ? #查看dev用戶空間下的所有運行的容器 k8s dev ?create_all ? ? ?#創(chuàng)建dev空間下所有服務(wù) k8s dev ?delall_app ? ? ? #刪除dev空間下的app服務(wù),除基礎(chǔ)服務(wù)mysql、 consul、 kafka、 redis、 zookeeper、mqtt 以外的所有服務(wù) k8s dev ?apply ?api ? ? ?#修改了yml配置文件,應(yīng)用配置生效 k8s dev ?create api ? ? ?#dev空間下創(chuàng)建一個api服務(wù) k8s dev ?delete api ? ? ?#dev空間下刪除一個api服務(wù) k8s dev ?scale ?api 2 ? ?#dev空間下把api服務(wù)擴容成2個pod k8s dev ?login ?api ? ? ?#dev空間下登錄api所在的docker容器 k8s dev ?logs ? api ? ? ?#dev空間用tail -f 命令的方式查看容器內(nèi)/home/deploy/api/logs/api.log 的日志 k8s dev ?error-logs api ?#dev空間用tail -f 命令的方式查看容器內(nèi)/home/deploy/api/logs/api.error.log 的日志 k8s dev ?push_jar ? ? ? ?#更新dev空間下所有容器的jar包版本,重啟所有容器,默認(rèn)拉取backend /-git最終版本,該版本為合并編譯成功后的最新版本號 k8s dev ?push_jar ?20170927-1731 ? #選擇指定的jar版本號20170927-1731 進(jìn)行更新 ,重啟所有容器 k8s dev ?clean api ? ? ? #如果編譯出錯,dev用戶空間用gradlew clean清理命令的方式清理編譯 k8s dev ?reinit-mysql ? ?#重新更新所有容器jar版本后api無法啟動,清空dev空間下的數(shù)據(jù)庫,重新創(chuàng)建導(dǎo)入數(shù)據(jù)批量操作 k8s dev ?scale api-geo 2 ?#在dev空間把api和geo 擴容 k8s dev ?delete api-geo ?#在dev空間刪除api 和geo服務(wù) k8s dev ?create api-geo ?#在dev空間下創(chuàng)建api和geo服務(wù)管理員專用命令,注意管理員第二個參數(shù)一定要填 k8s dev ?create_rsync ? ?#創(chuàng)建dev空間的rsync配置 k8s dev ?create_passwd ? #創(chuàng)建dev空間的解壓密碼下發(fā)密鑰 k8s dev ?create ? rbac ? #創(chuàng)建dev空間的集群授權(quán)認(rèn)證 k8s dev ?delete ? rbac ? #刪除dev空間的集群授權(quán)認(rèn)證 k8s dev ?delete_all ? ? ?#刪除dev空間下所有服務(wù)?
Kubernetes集群規(guī)劃和問題總結(jié)
1、集群資源規(guī)劃request +limit+maxpods+eviction參數(shù),需要計算好再配置,配置有問題可能導(dǎo)致資源利用不均衡,一部分節(jié)點資源利用過高,一部分節(jié)點資源利用過低。
2、Kubernetes Node節(jié)點一定要留有足夠的磁盤空間,跟據(jù)Pod個數(shù)和image大小決定磁盤空間數(shù)。
3、JDK無法獲取正確的CPU數(shù),默認(rèn)獲取的是宿主機CPU,會致創(chuàng)建的線程數(shù)過多,系統(tǒng)崩潰,可以通過:https://github.com/obmarg/libsysconfcpus.git 解決。
if [ "x$CONTAINER_CORE_LIMIT" != "x" ]; thenLIBSYSCONFCPUS="$CONTAINER_CORE_LIMIT"if [ ${LIBSYSCONFCPUS} -lt 2 ]; thenLIBSYSCONFCPUS=2fiexport LIBSYSCONFCPUS fi export LD_PRELOAD="/usr/local/lib/libsysconfcpus.so:$LD_PRELOAD"4、nfs-server一定要用async,充份利用緩存加快寫入速度,注意內(nèi)核版本bug。
5、應(yīng)用產(chǎn)生的日志必需要設(shè)置輪轉(zhuǎn)數(shù)和大小,防止過大日志撐暴宿主機磁盤。
6、發(fā)布版本越多,隨著下載鏡像版本越來越多,磁盤會撐爆,合理配置kubelet image gc參數(shù),配置gc回收優(yōu)化磁盤空間。
7、Docker CE以前的版本經(jīng)常會出現(xiàn)Docker失控,使用過程中整個節(jié)點容器無法刪除,無法創(chuàng)建,只能重啟,對業(yè)務(wù)影響很大,建議全部更新到18-CE版本,和Kubernetes容性更好。
8、節(jié)點的親和性和反親和Affinity一定要提前規(guī)劃好,為了達(dá)到高可用目的,多副本必需配置。
9、應(yīng)用異常檢測,跟據(jù)實際情況配置探針ReadinessProbe、LivenessProbe防止應(yīng)用假死,Kubernetes提前剔除有問題的Pod容器。
?
Q&A
Q:使用NFS有存在性能瓶頸或單點故障的問題嗎,如何解決,對于持久化要求高的Redis應(yīng)該采用哪種存儲?
A:具體看你的規(guī)模數(shù)量,測試、開發(fā)環(huán)境,單節(jié)點NFS毫無壓力,數(shù)據(jù)是先寫到緩存內(nèi)存,速度很快,我文章中的說的內(nèi)核注意bug,沒必要做高可用,公有云有NAS服務(wù),不必?fù)?dān)心,自建機房可以用drbd Keepalived vip。
?
Q:為什么網(wǎng)絡(luò)沒有使用Traefik,Spring Cloud的相關(guān)組件是怎么部署的,是用yaml文件還是使用Helm方式?
A:考慮到Traefik性能沒有nginx好,所以用nginx,yaml是自己寫的模板生成的,沒有用Helm。我們正在調(diào)研,Eureka可以單獨定制多個yaml互相注冊。與外部服務(wù)通過打通網(wǎng)絡(luò)直通,通過SVC對接。
?
Q:請問下所有環(huán)境都在一個集群,壓測怎么辦?
A:壓測只是對應(yīng)用產(chǎn)生壓力,你可以把需要壓測的應(yīng)用調(diào)度到不同的節(jié)點NodeSelecto隔離運行。
?
Q:對于局域網(wǎng)微信回調(diào)是如何做,沒有公網(wǎng)IP?
A:打通網(wǎng)絡(luò)之后,設(shè)置WIFI指向DNS為Kubernetes DNS,Service直接互通。
?
Q:Eureka注冊時服務(wù)IP用的什么?
A:Kubernetes集群內(nèi)會用的podip去注冊。
?
Q:有狀態(tài)應(yīng)用的場景,使用容器部署與傳統(tǒng)部署有啥區(qū)別,容器部署是否存在一些坑?
A:有狀態(tài)容器創(chuàng)建后,盡量少動,少遷移,遇到過卡住,容器無法遷移或刪除,重要的MySQL之類的建議放外部運行。
總結(jié)
以上是生活随笔為你收集整理的Spring Cloud Kubernetes容器化实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Consul和ZooKeeper的区别
- 下一篇: 从 Eclipse 到 IDEA,金字塔