文章目錄
怎麼跟你說
Service的出現,就是 解決ip不固定的問題 ,怎麼解決呢 ? 聽小劉慢慢道來html
當Pod宕機後從新生成時,其IP等狀態信息可能會變更,Service會根據Pod的Label對這些狀態信息進行監控和變動,保證上游服務不受Pod的變更而影響。node
1、Service 簡介
1.1 Service 概念
Kubernetes Service
定義了這樣一種抽象: Service
是一種能夠訪問 Pod
邏輯分組的策略, Service
一般是經過 Label Selector
訪問 Pod
組。linux
Service
可以提供負載均衡的能力,可是在使用上有如下限制:只提供 4 層負載均衡能力,而沒有 7 層功能,但有時咱們可能須要更多的匹配規則來轉發請求,這點上 4 層負載均衡是不支持的nginx
s 1.2 Service 類型
Service
在 K8s
中有如下四種類型:git
① ClusterIpgithub
默認類型,自動分配一個僅 Cluster
內部能夠訪問的虛擬 IP
② NodePort算法
在 ClusterIP
基礎上爲 Service
在每臺機器上綁定一個端口,這樣就能夠經過 : NodePort
來訪問該服務。 ③ LoadBalancershell
在 NodePort
的基礎上,藉助 Cloud Provider
建立一個外部負載均衡器,並將請求轉發到 NodePort
④ ExternalName後端
把集羣外部的服務引入到集羣內部來,在集羣內部直接使用。沒有任何類型代理被建立,這隻有 Kubernetes 1.7
或更高版本的 kube-dns
才支持。api
1.3 Service 基礎導論
- 客戶端訪問節點時經過
iptables
實現的 iptables
規則是經過kube-proxy
寫入的apiserver
經過監控kube-proxy
去進行對服務和端點的監控kube-proxy
經過pod
的標籤(lables
)去判斷這個斷點信息是否寫入到Endpoints
裏
2、代理
2.1 VIP 和 Service 代理
在 Kubernetes
集羣中,每一個 Node
運行一個 kube-proxy
進程。 kube-proxy
負責爲 Service
實現了一種 VIP
(虛擬 IP
)的形式,而不是 ExternalName
的形式。在 Kubernetes v1.0
版本,代理徹底在 userspace
。在 Kubernetes v1.1
版本,新增了 iptables
代理,但並非默認的運行模式。從 Kubernetes v1.2
起,默認就是 iptables
代理。在 Kubernetes v1.8.0-beta.0
中,添加了 ipvs
代理。
在 Kubernetes 1.14
版本開始默認使用 ipvs
代理。
在 Kubernetes v1.0
版本, Service
是 4 層( TCP
/ UDP over IP
)概念。在 Kubernetes v1.1
版本,新增了 Ingress API
( beta
版),用來表示 7 層( HTTP
)服務
爲什麼不使用 round-robin DNS
?
DNS
會在不少的客戶端裏進行緩存,不少服務在訪問 DNS
進行域名解析完成、獲得地址後不會對 DNS
的解析進行清除緩存的操做,因此一旦有他的地址信息後,無論訪問幾回仍是原來的地址信息,致使負載均衡無效
2.2 代理模式分類
① userspace 代理模式 ② iptables 代理模式
③ ipvs 代理模式
ipvs
代理模式中 kube-proxy
會監視 Kubernetes Service
對象和 Endpoints
,調用 netlink
接口以相應地建立 ipvs
規則並按期與 Kubernetes Service
對象和 Endpoints
對象同步 ipvs
規則,以確保 ipvs
狀態與指望一致。訪問服務時,流量將被重定向到其中一個後端 Pod
。
與 iptables
相似, ipvs
於 netfilter
的 hook
功能,但使用哈希表做爲底層數據結構並在內核空間中工做。這意味着 ipvs
能夠更快地重定向流量,而且在同步代理規則時具備更好的性能。此外, ipvs
爲負載均衡算法提供了更多選項,例如:
rr
:輪詢調度lc
:最小鏈接數dh
:目標哈希sh
:源哈希sed
:最短時間望延遲nq
:不排隊調度
3、Service 使用
3.1 ClusterIp
ClusterIP
主要在每一個 node
節點使用 iptables
,將發向 ClusterIP
對應端口的數據,轉發到 kube-proxy
中。而後 kube-proxy
本身內部實現有負載均衡的方法,並能夠查詢到這個 service
下對應 pod
的地址和端口,進而把數據轉發給對應的 pod
的地址和端口。 爲了實現圖上的功能,主要須要如下幾個組件的協同工做:
- apiserver:用戶經過
kubectl
命令向apiserver
發送建立service
的命令,apiserver
接收到請求後將數據存儲到etcd
中 - kube-proxy:
Kubernetes
的每一個節點中都有一個叫作kube-porxy
的進程,這個進程負責感知service
、pod
的變化,並將變化的信息寫入本地的iptables
規則中 - iptables:使用
NAT
等技術將virtualIP
的流量轉至endpoint
中
建立 myapp-deploy.yaml
文件
apiVersion: apps/v1 kind: Deployment metadata: name: myapp-deploy namespace: default spec: replicas: 3 selector: matchLabels: app: myapp release: stabel template: metadata: labels: app: myapp release: stabel env: test spec: containers: - name: myapp image: wangyanglinux/myapp:v2 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80
建立 Service
信息:
apiVersion: v1 kind: Service metadata: name: myapp namespace: default spec: type: ClusterIP selector: app: myapp release: stabel ports: - name: http port: 80 targetPort: 80
執行命令:
[root@master service] deployment.apps/myapp-deploy created [root@master service] NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myapp-deploy-6cc7c66999-5n2dj 1/1 Running 0 16s 10.244.1.26 worker1 <none> <none> myapp-deploy-6cc7c66999-dfgqb 1/1 Running 0 16s 10.244.1.27 worker1 <none> <none> myapp-deploy-6cc7c66999-wz6zk 1/1 Running 0 16s 10.244.2.30 worker2 <none> <none> [root@master service] Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a> [root@master service] service/myapp created [root@master service] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE myapp ClusterIP 10.104.96.7 <none> 80/TCP 8s [root@master service] IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 10.104.96.7:80 rr -> 10.244.1.26:80 Masq 1 0 0 -> 10.244.1.27:80 Masq 1 0 1 -> 10.244.2.30:80 Masq 1 0 1 [root@master service] myapp-deploy-6cc7c66999-5n2dj [root@master service] myapp-deploy-6cc7c66999-wz6zk [root@master service] myapp-deploy-6cc7c66999-dfgqb [root@master service] myapp-deploy-6cc7c66999-5n2dj
3.2 Handless Service
有時不須要或不想要負載均衡,以及單獨的 Service IP
。遇到這種狀況,能夠經過指定 spec.clusterIP
的值爲 None
來建立 Headless Service
。這類 Service
並不會分配 Cluster IP
, kube-proxy
不會處理它們,並且平臺也不會爲它們進行負載均衡和路由。
[root@master service] apiVersion: v1 kind: Service metadata: name: myapp-headless namespace: default spec: selector: app: myapp clusterIP: "None" ports: - port: 80 targetPort: 80 [root@master service]
3.3 NodePort
NodePort
的原理在於在 Node
上開了一個端口,將向該端口的流量導入到 kube-proxy
,而後由 kube-proxy
進一步到給對應的 pod
。
建立 Service
信息:
apiVersion: v1 kind: Service metadata: name: myapp namespace: default spec: type: NodePort selector: app: myapp release: stabel ports: - name: http port: 80 targetPort: 80
執行命令:
[root@master service] service/myapp configured [root@master service] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE myapp NodePort 10.104.96.7 <none> 80:30333/TCP 46m [root@master service] tcp6 0 0 :::30333 :::* LISTEN 3459/kube-proxy C:\Users\MrHu>curl 192.168.182.100:30333/hostname.html myapp-deploy-6cc7c66999-5n2dj
3.4 LoadBalancer
LoadBalancer
和 NodePort
實際上是同一種方式。區別在於 LoadBalancer
比 NodePort
多了一步,就是能夠調用 Cloud provider
去建立 LB
來向節點導流。
3.5 ExternalName
這種類型的 Service
經過返回 CNAME
和它的值,能夠將服務映射到 externalName
字段的內容( 例: hub.hc.com
)。 ExternalName Service
是 Service
的特例,它沒有 selector
,也沒有定義任何的端口和 Endpoint
。相反的,對於運行在集羣外部的服務,它經過返回該外部服務的別名這種方式來提供服務。
kind: Service apiVersion: v1 metadata: name: my-service-1 namespace: default spec: type: ExternalName externalName: hub.hc.com
當查詢主機 my-service.defalut.svc.cluster.local
時,集羣的 DNS
服務將返回一個值 hub.hc.com
的 CNAME
記錄。訪問這個服務的工做方式和其餘的相同,惟一不一樣的是重定向發生在 DNS
層,並且不會進行代理或轉發。
4、Ingress
4.1 Ingress 簡介
Service只支持4層負載均衡,而Ingress有7層功能
Nginx
能夠經過虛擬主機域名區分不一樣的服務,而每一個服務經過 upstream
進行定義不一樣的負載均衡池,再加上 location
進行負載均衡的反向代理,在平常使用中只須要修改 nginx.conf
便可實現,可是在 K8S
中又該如何實現這種方式調度呢?
K8S
引入了 ingress
自動進行服務的調度, ingress
包含兩大組件: ingress controller
和 ingress
。
- ingress:修改
Nginx
配置操做被抽象成了ingress
對象, - ingress controller:
ingress controller
經過與kubernetes API
交互,動態的去感知進集羣中Ingress
規則變化,而後讀取它,而後讀取它,按照它本身的模板生成一段nginx
配置,再寫到nginx Pod
中,最後reload
如下,工做流程以下圖:
Ingress 的安裝
① 下載 Ingress
鏡像:
[root@master ingress] REPOSITORY TAG IMAGE ID CREATED SIZE quay.io/kubernetes-ingress-controller/nginx-ingress-controller 0.25.0 02149b6f439f 13 months ago 508MB
② 拷貝配置文件 mandatory.yaml
、 service-nodeport.yaml
,位置參考 https://github.com/kubernetes/ingress-nginx/tree/nginx-0.25.0/deploy/static
。
③ 部署 ingress-controller
對外提供服務:
[root@master ingress] [root@master ingress] NAME READY STATUS RESTARTS AGE nginx-ingress-controller-7995bd9c47-kldqr 1/1 Running 0 13h
④ 給 ingress-controller
創建一個 servcie
,接收集羣外部流量
[root@master ingress] [root@master ingress] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx NodePort 10.106.6.160 <none> 80:31347/TCP,443:32445/TCP 13h
4.2 Ingress HTTP 代理訪問
建立 deployment
和 svc
[root@master ingress] apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-dm spec: replicas: 2 template: metadata: labels: name: nginx spec: containers: - name: nginx image: wangyanglinux/myapp:v1 imagePullPolicy: IfNotPresent ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-svc spec: ports: - port: 80 targetPort: 80 protocol: TCP selector: name: nginx [root@master ingress] [root@master ingress] NAME READY STATUS RESTARTS AGE nginx-dm-7d967c7ff5-kvz6f 1/1 Running 0 5m20s nginx-dm-7d967c7ff5-wk4jv 1/1 Running 0 5m21s [root@master ingress] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-svc ClusterIP 10.100.57.201 <none> 80/TCP 16m
建立 ingress
:
[root@master ingress] apiVersion: extensions/v1beta1 kind: Ingress metadata: name: nginx-test spec: rules: - host: www1.hc.com http: paths: - path: / backend: serviceName: nginx-svc servicePort: 80 [root@master ingress] [root@master ingress] NAME HOSTS ADDRESS PORTS AGE nginx-test www1.hc.com 80 23s [root@master ingress] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx NodePort 10.106.6.160 <none> 80:31347/TCP,443:32445/TCP 13h
在 Window
系統中配置 hosts
後進行訪問:
C:\Users\MrHu>curl www1.hc.com:31347/hostname.html nginx-dm-7d967c7ff5-wk4jv
4.3 Ingress HTTPS 代理訪問
建立證書,以及 cert
存儲方式:
[root@master cert] [root@master cert] secret/tls-secret created [root@master cert] NAME TYPE DATA AGE default-token-cjdrb kubernetes.io/service-account-token 3 6d14h tls-secret kubernetes.io/tls
建立 deployment
和 svc
:
[root@master ingress] apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-https spec: replicas: 2 template: metadata: labels: name: nginx2 spec: containers: - name: nginx image: wangyanglinux/myapp:v2 imagePullPolicy: IfNotPresent ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-svc-2 spec: ports: - port: 80 targetPort: 80 protocol: TCP selector: name: nginx2 [root@master ingress]
建立 ingress
:
[root@master ingress] apiVersion: extensions/v1beta1 kind: Ingress metadata: name: nginx-https spec: tls: - hosts: - www2.hc.com secretName: tls-secret rules: - host: www2.hc.com http: paths: - path: / backend: serviceName: nginx-svc-2 servicePort: 80 [root@master ingress] [root@master ingress] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-svc-2 ClusterIP 10.106.108.145 <none> 80/TCP 10m [root@master ingress] NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx NodePort 10.106.6.160 <none> 80:31347/TCP,443:32445/TCP 14h
在 Window
系統中配置 hosts
後進行訪問:
4.4 進行 BasicAuth
[root@master ingress] [root@master ingress] [root@master ingress] [root@master ingress] apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-with-auth annotations: nginx.ingress.kubernetes.io/auth-type: basic nginx.ingress.kubernetes.io/auth-secret: basic-auth nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo' spec: rules: - host: auth.hc.com http: paths: - path: / backend: serviceName: nginx-svc-2 servicePort: 80 [root@master ingress] [root@master ingress] NAME HOSTS ADDRESS PORTS AGE ingress-with-auth auth.hc.com 80 15s nginx-https www2.hc.com 80, 443 23m
在 Window
系統中配置 hosts
後進行訪問:
4.5 Nginx進行重寫
Nginx
重寫字段: 建立
ingress
:
[root@master ingress] apiVersion: extensions/v1beta1 kind: Ingress metadata: name: nginx-re annotations: nginx.ingress.kubernetes.io/rewrite-target: http://www1.hc.com:31347/hostname.html spec: rules: - host: re.hc.com http: paths: - path: / backend: serviceName: nginx-svc servicePort: 80 [root@master ingress]
在 Window
系統中配置 hosts
後進行訪問 re.hc.com:31347
:
你只管學習,我來負責記筆記😲 關注公衆號! ,更多筆記,等你來拿,謝謝