Kubernetes解決的另外一個痛點就是服務發現,服務發現機制和容器開放通路都是通過Service來實作的,把Deployment和Service關聯起來隻需要Label标簽相同就可以關聯起來形成負載均衡,基于kuberneres的DNS服務我們隻需要通路Service的名字就能以負載的方式通路到各個容器
Kubernetes官方文檔:
https://kubernetes.io/docs/reference/ Kubernetes官方Git位址: https://github.com/kubernetes/kubernetesPS:本系列中使用 KubernetesV1.8 RancherV1.6.14
1. Service的三種類型
Service有三種類型:
-
ClusterIP:預設類型,自動配置設定一個僅cluster内部可以通路的虛拟IP
常用于内部程式互相的通路,比如Gitlab需要通路Redis的postgresql,但是是内部使用的不需要外部通路,這個時候用ClusterIP就比較合适
-
NodePort:在ClusterIP基礎上為Service在每台機器上綁定一個端口,這樣就可以通過:NodePort來通路改服務
當我們的Gitlab需要提供通路,可以使用NodePort指定一個端口釋放服務,然後外層負載均衡映射就可以在外部通路,或者直接通路對應的端口
PS:NodePort方式暴露服務的端口的預設範圍(30000-32767)如果需要修改則在apiserver的啟動指令裡面添加如下參數 –service-node-port-range=1-65535
-
LoadBalancer:在NodePort的基礎上,借助cloud provider建立一個外部的負載均衡器,并将請求轉發到:NodePort
LoadBalancer是NodePort的更新版本,相當于和cloud provider結合不需要手動指定
我們經常使用的還是上面前兩種方式,我們先建立一個nginx-deployment鏡像2個Pod以便于接下來的使用
> vim nginx-deployment.yaml
apiVersion: extensions/v1beta1 # K8S對應的API版本
kind: Deployment # 對應的類型
metadata:
name: nginx-deployment
labels:
name: nginx-deployment
spec:
replicas: 2 # 鏡像副本數量
template:
metadata:
labels: # 容器的标簽 可和service關聯
app: nginx
spec:
containers:
- name: nginx # 容器名和鏡像
image: nginx
imagePullPolicy: Always
> kubectl create -f nginx-deployment.yaml
我們分别修改一下對應的輸出
> echo nginx1 > /usr/share/nginx/html/index.html
> echo nginx2 > /usr/share/nginx/html/index.html
安裝好ping 和 curl
> apt-get update
> apt-get install curl iputils-ping
2. ClusterIP
> vim test-clusterip-service.yaml
apiVersion: v1
kind: Service
metadata:
name: test-clusterip-service # 名稱
labels:
name: test-clusterip-service
spec:
type: ClusterIP # 開發端口的類型
selector: # service負載的容器需要有同樣的labels
app: nginx
ports:
- port: 80 # 通過service來通路的端口
targetPort: 80 # 對應容器的端口
> kubectl create -f test-clusterip-service.yaml
service "test-clusterip-service" created
> kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 12d
test-clusterip-service ClusterIP 10.43.202.97 <none> 80/TCP 18s
應為selector關聯上了Deployment的Label是以直接通路是可以通路到的具體nginx鏡像内,而且應為是兩個Pod是以是負載均衡之前我們修改了輸出多次通路可以看到不一樣的結果,基于Kube-DNS也可以使用Service名稱進行通路
root@nginx-deployment-68fcbc9696-wbgxr:/usr/share/nginx/html# curl 10.43.202.97
nginx2
root@nginx-deployment-68fcbc9696-wbgxr:/usr/share/nginx/html# curl test-clusterip-service
nginx1
3. NodePort
NodePort設計出來的主要目的就是對外部放出服務,也就是被外部能夠通路到,
> vim test-nodeport-service.yaml
apiVersion: v1
kind: Service
metadata:
name: test-nodeport-service # 名稱
labels:
name: test-nodeport-service
spec:
type: NodePort # 開發端口的類型
selector: # service負載的容器需要有同樣的labels
app: nginx
ports:
- port: 80 # 通過service來通路的端口
targetPort: 80 # 對應容器的端口
nodePort: 30080 # 對應需要放到主控端IP上的端口
> kubectl create -f test-nodeport-service.yaml
service "test-nodeport-service" created
> kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 12d
test-clusterip-service ClusterIP 10.43.202.97 <none> 80/TCP 14m
test-nodeport-service NodePort 10.43.101.60 <none> 80:30080/TCP 5s
此時在主控端上的30080端口就可以通路到我們的兩個Nginx容器了,如果機器綁定的有IP的話就可以直接通路或者在使用負載均衡對外放出服務
隻有在KUbernetes中才會受到Kube-DNS的影響,在主控端上無法使用test-nodeport-service通路Service隻能通過NodePort進行通路
[root@k8s-m ~]# curl 127.0.0.1:30080
nginx2
[root@k8s-m ~]# curl 127.0.0.1:30080
nginx1
4. Ingress
Service主要是處理4層TCP負載,但是往往對外需要放出HTTP七層協定的服務,一般我們在一套叢集下如果有多個HTTP服務會使用Nginx來統一接受80端口的資料然後通過域名或者是通路路徑來選擇不同的服務,Ingress就是解決這個問題誕生的,Ingress可以和Service結合對80端口的通路更具域名的過濾和通路路徑的過濾路由到對應的service,我們一起看幾個例子:
foo.bar.com -> 172.168.0.128 -> / foo nginx:80
/ bar nginx:80
> vim ing.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
backend:
serviceName: nginx
servicePort: 80
- path: /bar
backend:
serviceName: nginx
servicePort: 80
> kubectl create -f ing.yaml
> kubectl get ing
NAME RULE BACKEND ADDRESS
test -
foo.bar.com
/foo nginx:80
/bar nginx:80
foo.bar.com --| |-> foo.bar.com nginx:80
| 172.168.0.128 |
bar.foo.com --| |-> bar.foo.com nginx:80
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
serviceName: nginx
servicePort: 80
- host: bar.foo.com
http:
paths:
- backend:
serviceName: nginx
servicePort: 80
支援TLS需要使用Secret預先配置好對應的證書
apiVersion: v1
data:
tls.crt: base64 encoded cert
tls.key: base64 encoded key
kind: Secret
metadata:
name: testsecret
namespace: default
type: Opaque
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: no-rules-map
spec:
tls:
- secretName: testsecret
backend:
serviceName: nginx
servicePort: 80
使用Ingress能實作部分功能,但是筆者推薦使用網關服務(比如kong)來進行處理會更具靈活功能更下強大可控
小技巧
-
跨namespace通路Service
到這裡我們還沒有展開說NameSpace,NameSpace隔離了資源,比如你在A中不能建立兩個名字一樣的Service(Kubernetes其他資源同理),但是建立出一個NameSpace的是可以建立名字為Nginx的Service的
這個時候你在A空間中通路nginx-service的是A空間的容器,在B空間通路是B空間的nginx-service
但是如果需要在B空間通路A空間的Nginx-service要怎麼辦呢?
Kube提供在通路Service的時候末尾增加NameSpace名字進行通路,在B空間通路A的nginx-service可以使用nginx-service.A 進行通路