天天看點

K8S service (一)一、service

一、service

service作用

1.通過service為pod用戶端提供通路pod方法,即可用戶端通路pod入口 通過标簽動态感覺pod IP位址變化等

2.防止pod失聯

3.定義通路pod通路政策

4.通過label-selector相關聯

5.通過Service實作Pod的負載均衡(TCP/UDP 4層)

6.底層實作主要通過iptables和IPVS二種網絡模式

service底層實作原理

底層流量轉發與負載均衡實作均可以通過iptables或ipvs實作

iptables實作

K8S service (一)一、service
ipvs實作
K8S service (一)一、service

對比:

Iptables:

靈活,功能強大(可以在資料包不同階段對包進行操作) 規則周遊比對和更新,呈線性時延

IPVS:

工作在核心态,有更好的性能

排程算法豐富:rr,wrr,lc,wlc,ip hash...

service類型

service類型分為:

ClusterIP

預設,配置設定一個叢集内部可以通路的虛拟IP

NodePort

在每個Node上配置設定一個端口作為外部通路入口

LoadBalancer

工作在特定的Cloud Provider上,例如Google Cloud,AWS, OpenStack

ExternalName

表示把叢集外部的服務引入到叢集内部中來,即實作了叢集内部

pod和叢集外部的服務進行通信

二、ClusterIP類型

普通ClusterIP類型

ClusterIP根據是否生成ClusterIP又可分為普通Service和Headless Service 兩類:

普通Service:

為Kubernetes的Service配置設定一個叢集内部可通路的固定虛拟

IP(Cluster IP), 通過iptables或ipvs實作負載均衡通路pod。

Headless Service:

該服務不會配置設定Cluster IP, 也不通過kube-proxy做反向代理和負載均 衡。而是通過DNS提供穩定的網絡ID來通路,DNS會将headless service的後端直接解析為pod IP清單。

K8S service (一)一、service

指令建立普通service

1.準備YAML并建立deployment

vim deployment-nginx.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploy-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15-alpine
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80           
kubectl apply -f deployment-nginx.yml

2.檢視目前的service

kubectl get services # 或者 使用svc簡寫

預設隻有kubernetes本身自己的services

3.将名為nginx1的deployment映射端口

kubectl expose deployment deploy-nginx --port=80 --target-port=80 --protocol=TCP

說明:

預設是--type=ClusterIP,也可以使用--type="NodePort"

或 --type="ClusterIP"

4.驗證

kubectl get svc

kubectl get endpoints # endpoints可簡寫為ep

K8S service (一)一、service

5.通路(叢集内部任意節點可通路), 叢集外部不可通路

curl 10.68.101.47
K8S service (一)一、service

YAML建立普通service

1.直接使用上節内容建立的deployment,确認pod的标簽為app=nginx

kubectl get pods -l app=nginx

2.YAML編寫ClusterIP類型service

vim nginx_service.yml
apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: default
spec:
  type: ClusterIP           # ClusterIP類型,也是預設類型 
  ports:                    # 指定service 端口及容器端口
  - port: 80
    protocol: TCP
    targetPort: 80          # pod中的端口
  selector:                 # 指定後端pod标簽(不是deployment 的标簽)
     app: nginx
           
解釋如下:
apiVersion: v1
kind: Service
metadata:
  name: my-service
  namespace: default
spec:
  clusterIP: 10.2.11.22     # 這個ip可以不指定,讓它自動配置設定,需 要與叢集配置設定的網絡對應
  type: ClusterIP           # ClusterIP類型,也是預設類型 
  ports:                    # 指定service 端口及容器端口
  - port: 80
  protocol: TCP
    targetPort: 80          # pod中的端口
  selector:                 # 指定後端pod标簽(不是deployment 的标簽)
     app: nginx             # 表示此service關聯app:nginx标簽 的pod           

3, 應用YAML建立service

kubectl apply -f nginx_service.yml

4, 驗證檢視

K8S service (一)一、service

5.叢集内節點通路驗證

curl 10.68.23.55
K8S service (一)一、service

注意:叢集内節點都可通路,叢集外不可通路

驗證負載均衡

問題: 一共2個pod,那麼通路的到底是哪一個呢?

答案: 2個pod會負載均衡。

1.兩個pod裡做成不同的首頁友善測試負載均衡

kubectl exec -it deploy-nginx-6c9764bb69-jrnbh -- /bin/sh
cd  /usr/share/nginx/html/ 
echo web1 > index.html
exit

kubectl exec -it deploy-nginx-6c9764bb69-vswlq -- /bin/sh 
cd /usr/share/nginx/html/ 
echo web2 > index.html
exit           

2.測試

curl 10.68.23.55 # 多次通路有負載均衡
K8S service (一)一、service
curl 10.68.101.47 # 多次通路也有負載均衡,因為我兩個service關聯的是相同的兩個pod
K8S service (一)一、service

sessionAffinity(會話連接配接)

設定sessionAffinity為Clientip (類似nginx的ip_hash算法,lvs的source hash算法)

kubectl patch svc my-service -p '{"spec":{"sessionAffinity":"ClientIP"}}'

測試

curl 10.68.23.55 # 多次通路,會話粘貼
K8S service (一)一、service

設定回sessionAffinity為None

kubectl patch svc my-service -p '{"spec":{"sessionAffinity":"None"}}'

curl 10.68.23.55 # 多次通路, 回到負載均衡
K8S service (一)一、service

普通service的DNS解析

DNS服務監視Kubernetes API,為每一個Service建立DNS記錄用于域名解

DNS記錄格式為: ..svc.cluster.local

1, 檢視k8s的dns服務的IP

kubectl get svc -n kube-system |grep dns

2.查詢得到dns服務的IP為10.68.0.2, 查詢服務的endpoints

kubectl get endpoints
K8S service (一)一、service

3.在node上驗證dns解析

yum -y install bind-utils

nslookup deploy-nginx.default.svc.cluster.local 10.68.0.2

K8S service (一)一、service
nslookup my-service.default.svc.cluster.local 10.68.0.2
K8S service (一)一、service

注意:

在node上驗證不能直接curl my-service.default.svc.cluster.local去通路,因為在node上操 作,會預設走/etc/resolv.conf 裡的DNS,而不是走k8s自己的DNS 伺服器,是以上面驗證指令nslookup需要後面加上k8s自己的DNS服 務器IP

在pod裡就可以直接對service的域名進行操作了

4.在pod裡驗證dns解析

kubectl run busybox sleep 1000000 --image=busybox

kubectl get pods

K8S service (一)一、service

kubectl exec -it busybox -- /bin/sh

/ # ping my-service.default.svc.cluster.local.

#直接可以通過域名解析到service-IP

K8S service (一)一、service

因為busybox鏡像裡沒有curl和yum指令,是以用wget通過域名下載下傳pod 的首頁,也是OK的

/ # wget my-service.default.svc.cluster.local./index.html

cat index.html

rm index.html -rf

wget my-service.default.svc.cluster.local./index.html

K8S service (一)一、service

結論:

dns傳回的結果為service的IP,而不是pod的IP

也就是說客戶通路dns,解析為service的IP,再通過iptables或ipvs負載均衡到pod

iptables與ipvs排程方式修改

在kubeasz安裝時,預設現在指定為ipvs排程模式了,如果要改成 iptables模式,操作如下

systemctl cat kube-proxy |grep proxy-mode

K8S service (一)一、service

vim /etc/systemd/system/kube-proxy.service

--proxy-mode=iptables # k8s叢集所有節點都将此參數由 ipvs改成iptables

K8S service (一)一、service

改完之後,重新開機kube-proxy服務無法直接生效,需要把整個k8s叢集重 啟。

systemctl restart kube-proxy

systemctl daemon-reload

注意: 測試完後,請再改回成ipvs模式,重新開機叢集生效。(不建議使用iptables排程)

如果是kubeadm安裝,那麼預設為iptables排程模式,則可使用下面的方式修改

1, 修改kube-proxy的配置檔案

kubectl edit configmap kube-proxy -n kube-system

2, 檢視kube-system的namespace中kube-proxy有關的pod

kubectl get pods -n kube-system |grep kube-proxy

3, 驗證kube-proxy-xxx的pod中的資訊

4, 删除kube-proxy-xxx的所有pod,讓它重新拉取新的kube-proxy-xxx的 pod

kubectl delete pod kube-proxy-22x22 -n kube-system

kubectl delete pod kube-proxy-wk77n -n kube-system

kubectl delete pod kube-proxy-wnrmr -n kube-system

5, 随意檢視其中1個或3個kube-proxy-xxx的pod,驗證是否為IPVS方式了

6, 安裝ipvsadm檢視規則

yum install ipvsadm -y

ipvsadm -Ln

7, 再次驗證,就是标準的rr算法了

curl 10.2.11.22 # 多次通路,rr輪循

headless service

普通的ClusterIP service是service name解析為cluster ip,然後cluster ip對 應到後面的pod ip

而無頭service是指service name 直接解析為後面的pod ip

建立headless service

1.編寫YAML檔案

vim headless-service.yml
apiVersion: v1
kind: Service
metadata:
  name: headless-service
  namespace: default
spec:
  clusterIP: None                       # None就代表是無頭 service
  type: ClusterIP                       # ClusterIP類型,也 是預設類型
  ports:                                # 指定service 端口 及容器端口
  - port: 80                            # service ip中的端 口
    protocol: TCP
    targetPort: 80                      # pod中的端口 
  selector:                             # 指定後端pod标簽 
     app: nginx                         # 表示此service關聯 app:nginx标簽的pod           

2.應用YAML檔案建立無頭服務

kubectl apply -f headless-service.yml

3.驗證

K8S service (一)一、service

可以看到headless-service沒有CLUSTER-IP,用None表示

headless service的DNS解析

1. 檢視kube-dns服務的IP

2.能過DNS服務位址查找無頭服務的dns解析

nslookup headless-service.default.svc.cluster.local 10.68.0.2
K8S service (一)一、service

3.驗證pod的IP

kubectl get pods -o wide

headless service應用讨論

繼續閱讀