7. 丈母孃嫌我不懂K8s的Service概念,讓我去面壁

文章目錄

undefined

怎麼跟你說 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 類型

ServiceK8s中有如下四種類型: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

img

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 APIbeta版),用來表示 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相似, ipvsnetfilterhook功能,但使用哈希表做爲底層數據結構並在內核空間中工做。這意味着 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-proxyKubernetes的每一個節點中都有一個叫作 kube-porxy的進程,這個進程負責感知 servicepod的變化,並將變化的信息寫入本地的 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 IPkube-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

LoadBalancerNodePort實際上是同一種方式。區別在於 LoadBalancerNodePort多了一步,就是能夠調用 Cloud provider去建立 LB來向節點導流。

3.5 ExternalName

這種類型的 Service經過返回 CNAME和它的值,能夠將服務映射到 externalName字段的內容( 例: hub.hc.com )。 ExternalName ServiceService的特例,它沒有 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.comCNAME記錄。訪問這個服務的工做方式和其餘的相同,惟一不一樣的是重定向發生在 DNS層,並且不會進行代理或轉發。

4、Ingress

4.1 Ingress 簡介

Service只支持4層負載均衡,而Ingress有7層功能

Nginx能夠經過虛擬主機域名區分不一樣的服務,而每一個服務經過 upstream進行定義不一樣的負載均衡池,再加上 location進行負載均衡的反向代理,在平常使用中只須要修改 nginx.conf便可實現,可是在 K8S中又該如何實現這種方式調度呢?

K8S引入了 ingress自動進行服務的調度, ingress包含兩大組件: ingress controlleringress

  • ingress:修改 Nginx配置操做被抽象成了 ingress對象,
  • ingress controlleringress 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.yamlservice-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 代理訪問

建立 deploymentsvc

[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

建立 deploymentsvc:

[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

你只管學習,我來負責記筆記😲 關注公衆號! ,更多筆記,等你來拿,謝謝

相關文章
相關標籤/搜索