廢話:先講述一個k8s重要概念刨秆,我覺得這個概念是整個k8s集群實現(xiàn)微服務的最核心的概念
Service
Service定義了Pod的邏輯集合和訪問該集合的策略,是真實服務的抽象蚊逢。Service提供了一個統(tǒng)一的服務訪問入口以及服務代理和發(fā)現(xiàn)機制,用戶不需要了解后臺Pod是如何運行卦方。只需要將一組跑同一服務的pod池化成一個service,k8s集群會自動給這個service分配整個集群唯一ip和端口號(這個端口號自己在yaml文件中定義)趁俊,一個service定義了訪問pod的方式脚作,就像單個固定的IP地址和與其相對應的DNS名之間的關系警没。
Service其實就是我們經常提起的微服務架構中的一個"微服務"匈辱,每個微服務后端負載均衡多個業(yè)務pod,由版本控制(deployment)控制pod數(shù)量惠奸,保證服務的高可靠性與冗余性梅誓。最終我們的系統(tǒng)由多個提供不同業(yè)務能力而又彼此獨立的微服務單元所組成,服務之間通過TCP/IP(k8s集群分配的整個集群唯一的)進行通信佛南,從而形成了我們強大而又靈活的彈性網絡,擁有了強大的分布式能力嵌言、彈性擴展能力嗅回、容錯能力;
理解service這個概念之后摧茴,我們跑去service后端看看具體是怎么實現(xiàn)的绵载?
需求:有一個問題就是現(xiàn)在我的業(yè)務分配在多個Pod上,那么如果我某個Pod死掉豈不是業(yè)務完蛋了,當然也會有人說Pod死掉沒問題啊娃豹,K8S自身機制Deployment和Controller會動態(tài)的創(chuàng)建和銷毀Pod來保證應用的整體穩(wěn)定性焚虱,那這時候還會有問題,那就是每個Pod產生的IP都是動態(tài)的懂版,那所以說重新啟動了我對外訪問的IP豈不是要變了鹃栽,別急,下面我們來解決下這個問題躯畴。
可以通過Service來解決如上所遇到的問題
Service是kubernetes最核心的概念民鼓,通過創(chuàng)建Service,可以為一組具有相同功能的容器應用提供一個統(tǒng)一的入口地址蓬抄,并且將請求進行負載分發(fā)到后端的各個容器應用上丰嘉。至于如何負載分發(fā),我們不用去擔心嚷缭,k8s自己搞定饮亏。
簡單來說Service就是一個把所有Pod統(tǒng)一成一個組,然后對外提供固定一個IP阅爽,具體是哪些Pod克滴,可以通過之前介紹到的Label標簽來進行設置,假設一個pod死掉优床,副本控制器在生成一個pod,這是pod ip肯定會變劝赔,但是我們不去關心你pod ip是多少,我們只知道service ip 沒變就好了胆敞,因為新的pod 早就加入到我的service中了着帽,各個服務之間通信是通過service 唯一ip來通信的。
上述所有操作移层,為什么實現(xiàn)了所謂的“”微服務”仍翰,舉個大家都懂的例子;
一套簡單的架構观话,nginx做反向代理予借,后端web為8個tomcat實例,在k8s集群中怎么實現(xiàn)呢频蛔,我只需要跑8個pod,每個pod運行tomcat容器灵迫,service池化這8個pod,而且副本控制會自動動態(tài)控制pod數(shù)量,少于8個他會創(chuàng)建到8個晦溪,多余8個會自動刪除到8個瀑粥。而且我們訪問service ip,k8s中的kube-proxy會自動負載均衡后端的8個pod,這一套服務集群內部訪問三圆,只需要一個service ip 和端口號就可以狞换;同理避咆,redis集群,同樣可以這樣實現(xiàn)修噪,每個service相當于微服務查库,各個服務之間靈活通信。
廢話不多說黄琼,咱們直接實操演示
創(chuàng)建副本控制資源名為nginx-deployment樊销,運行兩個pod,每個pod運行一個nginx容器适荣,容器端口開放80.
[root@master yaml]# cat nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx 就是說哪些Pod被Service池化是根據(jù)Label標簽來的现柠,此行nginx字樣,后面我們創(chuàng)建Service會用到
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
kubectl create -f nginx.yaml
deployment.apps/nginx-deployment created
創(chuàng)建Service 池化剛才的兩個nginx pod
[root@master yaml]# cat nginx-svc.yml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 8080 這個資源(svc)開放的端口
targetPort: 80
selector選擇之前Label標簽為nginx的Pod作為Service池化的對象弛矛,
最后說的是把Service的8080端口映射到Pod的80端口够吩。
kubectl apply -f nginx-svc.yml
service/nginx-svc created
創(chuàng)建完成之后nginx-svc會分配到一個cluster-ip,可以通過該ip訪問后端nginx業(yè)務丈氓。
那它是怎么實現(xiàn)的呢周循?答案是通過iptables實現(xiàn)的地址轉換和端口轉換,自己去研究
那這時候有人說了万俗,還是不能外網訪問啊湾笛,別急下面我們來進行外網地址訪問設置。在實際生產環(huán)境中闰歪,對Service的訪問可能會有兩種來源:Kubernetes集群內部的程序(Pod)和Kubernetes集群外部嚎研,為了滿足上述的場景,Kubernetes service有以下三種類型:
1.ClusterIP:提供一個集群內部的虛擬IP(與Pod不在同一網段)库倘,以供集群內部的pod之間通信使用临扮。
2.NodePort:在每個Node上打開一個隨機端口并且每個Node的端口都是一樣的,通過<NodeIP>:NodePort的方式Kubernetes集群外部的程序可以訪問Service教翩。
3.LoadBalancer:利用Cloud Provider特有的Load Balancer對外提供服務杆勇,Cloud Provider負責將Load Balancer的流量導向Service
本篇文章我著重講下第二種方式,也就是NodePort方式饱亿,修改nginx-svc.yml文件蚜退,也就是剛才前面創(chuàng)建的Service文件,相信細心的同學會發(fā)現(xiàn)在之前截圖的時候已經做好了NodePort彪笼,因為我的環(huán)境已經配置好了所以這樣就不在截圖了钻注,配置很簡單,可以網上看下截圖杰扫,就是添加一個type:NodePort队寇,然后重新創(chuàng)建下nginx-svc,命令的話和創(chuàng)建的命令一樣章姓,我們來看看創(chuàng)建完事的結果佳遣。