07 . Kubernetes之Service

kubernetes有三種網路

1. Node Network
2. Pod Network
3. Cluster Network

Service-網路代理模式

**userspce: 1.1-

**三種代理模式
1.1版本使用的userspace,性能低,因為用戶請求先要到內核空間,然後到主機用戶空間Kube-Proxy,由kube-proxy封裝報文再返回到內核空間,再到iptables分發.

2.iptables
1.10版本就開始使用iptables,因為他直接工作在內核,性能相比之前提升了很多,他是基於四層的轉發,不會經過用戶層kube-proxy,直接調度給相關的Pod

3.ipvs
1.11版本默認ipvs,如果沒激活降級為iptables
1.8版本增加了ipvs為了能最大的發揮轉發的性能,client請求到達了直接調度給Pod網路地址範圍.

Service類型

類型

ExternalName: # 把集群外部服務引入到集群內部直接使用
ClusterIP: # 默認,僅用於集群內部通訊,如果要接入外部需要NodePort;
NodePort:
LoadBalancer:  # 表示我們把kubernetes集群部署在虛擬機上,虛擬機工作在雲環境上,雲環境支援LBAAS,負載均衡一鍵調用.

資源記錄
SVC_NAME,NS_NAME,DOMAIN,LTD
svc.cluster.local
redis.default.svc.cluster.local

Example1.使用清單創建SVC

cat pod-service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  clusterIP: 10.96.122.10 
  type: NodePort 
  ports:
  - port: 80
    targetPort: 80 
    nodePort: 30000

cat pod-deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: http
          containerPort: 80
kubectl describe svc redis
kubectl get endpoints

使用集群外的機器訪問看下什麼效果

while true; do curl 172.19.0.26:30000/hostname.html ; sleep 2;done
myapp-deploy-7d574d56c7-2tsdx
myapp-deploy-7d574d56c7-hcw8s
myapp-deploy-7d574d56c7-hcw8s
myapp-deploy-7d574d56c7-hcw8s
myapp-deploy-7d574d56c7-2tsdx


kubectl patch svc redis -p '{"spec":{"sessionAffinity":"ClientIP"}}'	
# sessionAffinity,讓同一個客戶端IP訪問固定的一個Pod
myapp-deploy-7d574d56c7-hcw8s
myapp-deploy-7d574d56c7-hcw8s
myapp-deploy-7d574d56c7-hcw8s
myapp-deploy-7d574d56c7-hcw8s
myapp-deploy-7d574d56c7-hcw8s
myapp-deploy-7d574d56c7-hcw8s
myapp-deploy-7d574d56c7-hcw8s

kubectl patch svc redis -p '{"spec":{"sessionAffinity":"None"}}'
# 修改成默認值None
myapp-deploy-7d574d56c7-2tsdx
myapp-deploy-7d574d56c7-2tsdx
myapp-deploy-7d574d56c7-hcw8s
myapp-deploy-7d574d56c7-2tsdx
myapp-deploy-7d574d56c7-2tsdx
myapp-deploy-7d574d56c7-hcw8s

# Service到Pod是有一個中間層,Endpoints,他也是一個標準Kubernetes對象,地址加埠,關聯到後端的Pod

創建一個無頭IP

cat pod-svc-head.yaml 
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
  namespace: default
spec:
  selector:
    app: myapp
    release: canary
  clusterIP: "None"
  ports:
  - port: 80
    targetPort: 80

kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP        5d17h
myapp-svc    ClusterIP   None           <none>        80/TCP         8m16s

使用清單定義Service服務代理

Example

cat service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 80
  - name: https
    protocol: TCP
    port: 443
    targetPort: 443 
# 通過svc的ClusterIP地址加上埠就能訪問此處app指定的服務

kubectl get svc  
NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE  
kubernetes      ClusterIP   10.96.0.1      <none>        443/TCP          29h  
my-service      ClusterIP   10.96.87.66    <none>        80/TCP,443/TCP   61s


kubectl get endpoints my-service
NAME         ENDPOINTS   AGE
my-service   <none>      3m25s

因為匹配不到MyApp標籤的Pod,我們去修改下my-service裡面標籤為已有Pod的標籤

kubectl edit svc/my-service
28   selector:
29     app: nginx
30   sessionAffinity: None
31   type: ClusterIP

# 然後我們去查看service後面有不有代理的Pod
kubectl get ep
kubectl get ep
NAME            ENDPOINTS                                                  AGE
kubernetes      192.168.78.7:6443                                          29h
my-service      10.244.2.11:80,10.244.3.13:80,10.244.3.14:80 + 3 more...   6m37s
nginx-service   <none>   

# 接下來訪問svc裡面的IP+埠即可

服務發現(環境變數與KubeDNS)

環境變數

當一個Pod運行在Node,kubelet會為每個容器添加一組環境變數,Pod容器中程式就可以使用這些環境變數發現Service。這些環境變數格式如下:

(SVCNAME)_SERVICE_HOST
(SVCNAME)_SERVICE_PORT
其中服務名和埠名轉為大寫,連字元轉換為下劃線.

限制

# 1. Pod和Service的創建順序是由要求的,Service必須在Pod創建之前被創建,否則環境變數不會設置到Pod上.
# 2. Pod只能獲取同個NameSpace中的Service環境變數.

DNS

DNS服務監視Kubernetes API,為每一個Service創建DNS記錄用於域名解析,這樣Pod中可以通過DNS域名獲取Service的訪問地址.

Example1
我們先創建一個busybox的pod

 cat busybox.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: busybox
  namespace: default
spec:
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    imagePullPolicy: IfNotPresent
    name: busybox
  restartPolicy: Always

kubectl exec -it busybox /bin/sh
/ # env |head -6
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
MY_SERVICE_PORT_443_TCP_ADDR=10.96.87.66
MY_SERVICE_PORT_80_TCP=tcp://10.96.87.66:80
HOSTNAME=busybox
SHLVL=1
# 我們每創建一個Pod都會在env裡面創建這些環境變數
[root@master ~]# kubectl get svc
NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes      ClusterIP   10.96.0.1      <none>        443/TCP          29h
my-service      ClusterIP   10.96.87.66    <none>        80/TCP,443/TCP   22m
nginx-service   ClusterIP   10.96.60.189   <none>        8080/TCP         24m
[root@master ~]# kubectl exec -it busybox /bin/sh
/ # echo ${MY_SERVICE_SERVICE_HOST_PORT}
10.96.87.66
# 我們可以通過一些變數獲取相應的值
# 但是我們要先創建service,後面的Pod才能獲取service那些環境變數.

Example2(DNS)
DNS可以拋去上面的那種Pod先後創建順序限制
//github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/deployments/kube-dns.yaml

# 到這個網址下載yaml文件創建kube-dns
# 注意修改配置文件的clusterIP: 通過ps -ef |grep kubelet查看
# 注意配置文件是要訪問外國源的,注意換成中國源.