kubernetes 服務(wù)訪問

簡介

kubernetes 使用service和ingress共同構(gòu)建了,外部訪問k8s內(nèi)部容器的通道。

Service

概念

Service是定義一系列Pod以及訪問這些Pod的策略的一層抽象。

Pods是短暫的,那么重啟時(shí)IP地址可能會(huì)改變,為了能從前端容器正確可靠地指向后臺(tái)容器

Service通過Label找到Pod組。因?yàn)镾ervice是抽象的,所以在圖表里通常看不到它們的存在,這也就讓這一概念更難以理解。

現(xiàn)在,假定有2個(gè)后臺(tái)Pod,并且定義后臺(tái)Service的名稱為‘backend-service’,lable選擇器為(tier=backend, app=myapp)。backend-service 的Service會(huì)完成如下兩件重要的事情:

  • 會(huì)為Service創(chuàng)建一個(gè)本地集群的DNS入口,因此前端Pod只需要DNS查找主機(jī)名為 ‘backend-service’,就能夠解析出前端應(yīng)用程序可用的IP地址。
  • 現(xiàn)在前端已經(jīng)得到了后臺(tái)服務(wù)的IP地址,但是它應(yīng)該訪問2個(gè)后臺(tái)Pod的哪一個(gè)呢?Service在這2個(gè)后臺(tái)Pod之間提供透明的負(fù)載均衡,會(huì)將請求分發(fā)給其中的任意一個(gè)(如下面的動(dòng)畫所示)。通過每個(gè)Node上運(yùn)行的代理(kube-proxy)完成。

下述動(dòng)畫展示了Service的功能。注意該圖作了很多簡化。如果不進(jìn)入網(wǎng)絡(luò)配置,那么達(dá)到透明的負(fù)載均衡目標(biāo)所涉及的底層網(wǎng)絡(luò)和路由相對先進(jìn)。


k8s-service.gif

在實(shí)際生產(chǎn)環(huán)境中,對Service的訪問可能會(huì)有兩種來源:Kubernetes集群內(nèi)部的程序(Pod)和Kubernetes集群外部,為了滿足上述的場景,Kubernetes service有以下三種類型:

  • ClusterIP:提供一個(gè)集群內(nèi)部的虛擬IP以供Pod訪問。
  • NodePort:在每個(gè)Node上打開一個(gè)端口以供外部訪問。
  • LoadBalancer:通過外部的負(fù)載均衡器來訪問。

ClusterIP

此模式會(huì)提供一個(gè)集群內(nèi)部的虛擬IP(與Pod不在同一網(wǎng)段),以供集群內(nèi)部的pod之間通信使用。
ClusterIP也是Kubernetes service的默認(rèn)類型。

clusterip.png

為了實(shí)現(xiàn)圖上的功能主要需要以下幾個(gè)組件的協(xié)同工作

  • apiserver
    用戶通過kubectl命令向apiserver發(fā)送創(chuàng)建service的命令,apiserver接收到請求以后將數(shù)據(jù)存儲(chǔ)到etcd中。
  • kube-proxy
    kubernetes的每個(gè)節(jié)點(diǎn)中都有一個(gè)叫做kube-proxy的進(jìn)程,這個(gè)進(jìn)程負(fù)責(zé)感知service,pod的變化,并將變化的信息寫入本地的
    iptables中。
  • iptables
    使用NAT等技術(shù)將virtualIP的流量轉(zhuǎn)至endpoint中。
    下面我們實(shí)際發(fā)布一個(gè)Service,能夠更清晰的了解到Service是如何工作的。

發(fā)布一個(gè)rc,并指定replices count為3.

yancey@ yancey-macbook kubernetes-1$kubectl create -f rc_nginx.yaml
yancey@ yancey-macbook kubernetes-1$kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
k8s-master-core-v2-01    4/4       Running   0          8m
k8s-proxy-core-v2-01     1/1       Running   0          8m
nginx-controller-6bovu   1/1       Running   0          4m
nginx-controller-iowux   1/1       Running   0          4m
nginx-controller-o7m6u   1/1       Running   0          4m
yancey@ yancey-macbook kubernetes-1$kubectl describe pod nginx-controller-6bovu
Name:       nginx-controller-6bovu
Namespace:  default
Node:       core-v2-01/172.17.8.101
Start Time: Fri, 17 Jun 2016 15:22:20 +0800
Labels:     app=nginx
Status:     Running
IP:     10.1.13.3
Controllers:    ReplicationController/nginx-controller

發(fā)布一個(gè)service,并指定步驟1中的label

yancey@ yancey-macbook kubernetes-1$kubectl create -f service_nginx.yaml
yancey@ yancey-macbook kubernetes-1$kubectl get svc
NAME            CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes      10.0.0.1     <none>        443/TCP    9m
nginx-service   10.0.0.252   <none>        8000/TCP   4m

kubernetes為nginx-server這個(gè)service創(chuàng)建了一個(gè)10.0.0.252這個(gè)ClusterIP,也可以稱為VirtualIP.

yancey@ yancey-macbook kubernetes-1$kubectl get ep
NAME            ENDPOINTS                                AGE
kubernetes      172.17.8.101:6443                        9m
nginx-service   10.1.13.2:80,10.1.13.3:80,10.1.13.4:80   4m

查看endpoint信息,發(fā)現(xiàn)nginx-service一共有三個(gè)endpoint地址,分別對應(yīng)nginx的三個(gè)pod。

查看iptables,觀察其NAT表中的信息(只截取了部分和這個(gè)service有關(guān)的信息)
查看iptables中NAT表的命令: iptables -L -v -n -t nat

Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
   37  2766 KUBE-SERVICES  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes service portals */
   33  2112 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

在PREROUTING鏈中會(huì)先匹配到KUBE-SERVICES這個(gè)Chain。

Chain KUBE-SERVICES (2 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-SVC-GKN7Y2BSGW4NJTYL  tcp  --  *      *       0.0.0.0/0            10.0.0.252           /* default/nginx-service: cluster IP */ tcp dpt:8000
   18  1080 KUBE-NODEPORTS  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL

所有destinationIP為10.0.0.252的包都轉(zhuǎn)到KUBE-SVC-GKN7Y2BSGW4NJTYL這個(gè)Chain

Chain KUBE-SVC-GKN7Y2BSGW4NJTYL (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-SEP-7ROBBXFV7SD4AIRW  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/nginx-service: */ statistic mode random probability 0.33332999982
    0     0 KUBE-SEP-XY3F6VJIZ7ELIF4Z  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/nginx-service: */ statistic mode random probability 0.50000000000
    0     0 KUBE-SEP-JIDZHFC4A3T535AK  all  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/nginx-service: */

這里能看到請求會(huì)平均執(zhí)行KUBE-SEP-7ROBBXFV7SD4AIRW,KUBE-SEP-XY3F6VJIZ7ELIF4Z,KUBE-SEP-XY3F6VJIZ7ELIF4Z這三個(gè)Chain.最后我們看下KUBE-SEP-7ROBBXFV7SD4AIRW這個(gè)Chain做了什么

Chain KUBE-SEP-7ROBBXFV7SD4AIRW (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-MARK-MASQ  all  --  *      *       10.1.13.2            0.0.0.0/0            /* default/nginx-service: */
    0     0 DNAT       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/nginx-service: */ tcp to:10.1.13.2:80

這個(gè)Chain使用了DNAT規(guī)則將流量轉(zhuǎn)發(fā)到10.1.13.2:80這個(gè)地址。至此從Pod發(fā)出來的流量通過本地的iptables將流量轉(zhuǎn)至了service背后的pod上。

NodePort

Kubernetes將會(huì)在每個(gè)Node上打開一個(gè)端口并且每個(gè)Node的端口都是一樣的,通過<NodeIP>:NodePort的方式Kubernetes集群外部的程序可以訪問Service。

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  type: NodePort
  ports:
  - port: 8000
    targetPort: 80
    protocol: TCP
  # just like the selector in the replication controller,
  # but this time it identifies the set of pods to load balance
  # traffic to.
  selector:
    app: nginx

發(fā)布這個(gè)service,可以看到已經(jīng)隨機(jī)分配了一個(gè)NodePort端口。

yancey@ yancey-macbook kubernetes-1$kubectl get svc nginx-service -o yaml
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: 2016-06-18T03:29:42Z
  name: nginx-service
  namespace: default
  resourceVersion: "1405"
  selfLink: /api/v1/namespaces/default/services/nginx-service
  uid: e50ba23a-3504-11e6-a94f-080027a75e9e
spec:
  clusterIP: 10.0.0.229
  ports:
  - nodePort: 30802
    port: 8000
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}

觀察Iptables中的變化,KUBE-NODEPORTS這個(gè)Chain中增加了如下內(nèi)容

Chain KUBE-NODEPORTS (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 KUBE-MARK-MASQ  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/nginx-service: */ tcp dpt:30802
    0     0 KUBE-SVC-GKN7Y2BSGW4NJTYL  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            /* default/nginx-service: */ tcp dpt:30802

可以看到流量會(huì)轉(zhuǎn)至KUBE-SVC-GKN7Y2BSGW4NJTYL這個(gè)Chain中處理一次,也就是ClusterIP中提到的通過負(fù)載均衡將流量平均分配到3個(gè)endpoint上。

LoadBalancer

Ingress

概念

通常情況下,service和pod僅可在集群內(nèi)部網(wǎng)絡(luò)中通過IP地址訪問。所有到達(dá)邊界路由器的流量或被丟棄或被轉(zhuǎn)發(fā)到其他地方。從概念上講,可能像下面這樣:

    internet
        |
  ------------
  [ Services ]

Ingress是授權(quán)入站連接到達(dá)集群服務(wù)的規(guī)則集合。

    internet
        |
   [ Ingress ]
   --|-----|--
   [ Services ]

你可以給Ingress配置提供外部可訪問的URL、負(fù)載均衡、SSL、基于名稱的虛擬主機(jī)等。用戶通過POST Ingress資源到API server的方式來請求ingress。 Ingress controller負(fù)責(zé)實(shí)現(xiàn)Ingress,通常使用負(fù)載平衡器,它還可以配置邊界路由和其他前端,這有助于以HA方式處理流量。

你需要一個(gè)Ingress Controller來實(shí)現(xiàn)Ingress,單純的創(chuàng)建一個(gè)Ingress沒有任何意義。

GCE/GKE會(huì)在master節(jié)點(diǎn)上部署一個(gè)ingress controller。你可以在一個(gè)pod中部署任意個(gè)自定義的ingress controller。你必須正確地annotate每個(gè)ingress,比如 運(yùn)行多個(gè)ingress controller 和 關(guān)閉glbc

為了使Ingress正常工作,集群中必須運(yùn)行Ingress controller。 這與其他類型的控制器不同,其他類型的控制器通常作為kube-controller-manager二進(jìn)制文件的一部分運(yùn)行,在集群啟動(dòng)時(shí)自動(dòng)啟動(dòng)。 你需要選擇最適合自己集群的Ingress controller或者自己實(shí)現(xiàn)一個(gè)。

實(shí)踐

單Service Ingress

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:
  backend:
    serviceName: testsvc
    servicePort: 80

使用kubectl create -f命令創(chuàng)建,然后查看ingress:

$ kubectl get ing
NAME                RULE          BACKEND        ADDRESS
test-ingress        -             testsvc:80     107.178.254.228

107.178.254.228就是Ingress controller為了實(shí)現(xiàn)Ingress而分配的IP地址。RULE列表示所有發(fā)送給該IP的流量都被轉(zhuǎn)發(fā)到了BACKEND所列的Kubernetes service上。

簡單展開

如前面描述的那樣,kubernete pod中的IP只在集群網(wǎng)絡(luò)內(nèi)部可見,我們需要在邊界設(shè)置一個(gè)東西,讓它能夠接收ingress的流量并將它們轉(zhuǎn)發(fā)到正確的端點(diǎn)上。這個(gè)東西一般是高可用的loadbalancer。使用Ingress能夠允許你將loadbalancer的個(gè)數(shù)降低到最少,例如,嫁入你想要?jiǎng)?chuàng)建這樣的一個(gè)設(shè)置:

foo.bar.com -> 178.91.123.132 -> / foo    s1:80
                                 / bar    s2:80

你需要一個(gè)這樣的ingress:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /foo
        backend:
          serviceName: s1
          servicePort: 80
      - path: /bar
        backend:
          serviceName: s2
          servicePort: 80

使用kubectl create -f創(chuàng)建完ingress后:

$ kubectl get ing
NAME      RULE          BACKEND   ADDRESS
test      -
          foo.bar.com
          /foo          s1:80
          /bar          s2:80

只要服務(wù)(s1,s2)存在,Ingress controller就會(huì)將提供一個(gè)滿足該Ingress的特定loadbalancer實(shí)現(xiàn)。 這一步完成后,您將在Ingress的最后一列看到loadbalancer的地址。

基于名稱的虛擬主機(jī)

Name-based的虛擬主機(jī)在同一個(gè)IP地址下?lián)碛卸鄠€(gè)主機(jī)名。

foo.bar.com --|                 |-> foo.bar.com s1:80
              | 178.91.123.132  |
bar.foo.com --|                 |-> bar.foo.com s2:80

下面這個(gè)ingress說明基于 Host header的后端loadbalancer的路由請求:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - backend:
          serviceName: s1
          servicePort: 80
  - host: bar.foo.com
    http:
      paths:
      - backend:
          serviceName: s2
          servicePort: 80

默認(rèn)backend:一個(gè)沒有rule的ingress,如前面章節(jié)中所示,所有流量都將發(fā)送到一個(gè)默認(rèn)backend。你可以用該技巧通知loadbalancer如何找到你網(wǎng)站的404頁面,通過制定一些列rule和一個(gè)默認(rèn)backend的方式。如果請求header中的host不能跟ingress中的host匹配,并且/或請求的URL不能與任何一個(gè)path匹配,則流量將路由到你的默認(rèn)backend。

TLS

你可以通過指定包含TLS私鑰和證書的 secret 來加密Ingress。 目前,Ingress僅支持單個(gè)TLS端口443,并假定TLS termination。 如果Ingress中的TLS配置部分指定了不同的主機(jī),則它們將根據(jù)通過SNI TLS擴(kuò)展指定的主機(jī)名(假如Ingress controller支持SNI)在多個(gè)相同端口上進(jìn)行復(fù)用。 TLS secret中必須包含名為tls.crttls.key的密鑰,這里面包含了用于TLS的證書和私鑰,例如:

apiVersion: v1
data:
  tls.crt: base64 encoded cert
  tls.key: base64 encoded key
kind: Secret
metadata:
  name: testsecret
  namespace: default
type: Opaque

在Ingress中引用這個(gè)secret將通知Ingress controller使用TLS加密從將客戶端到loadbalancer的channel:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: no-rules-map
spec:
  tls:
    - secretName: testsecret
  backend:
    serviceName: s1
    servicePort: 80

各種Ingress controller支持的TLS功能之間存在差距。 請參閱有關(guān)
nginx,gce 或任何其他平臺(tái)特定Ingress controller的文檔,以了解TLS在你的環(huán)境中的工作原理。

Ingress controller啟動(dòng)時(shí)附帶一些適用于所有Ingress的負(fù)載平衡策略設(shè)置,例如負(fù)載均衡算法,后端權(quán)重方案等。更高級(jí)的負(fù)載平衡概念(例如持久會(huì)話,動(dòng)態(tài)權(quán)重)尚未在Ingress中公開。 你仍然可以通過 service loadbalancer獲取這些功能。 隨著時(shí)間的推移,我們計(jì)劃將適用于跨平臺(tái)的負(fù)載平衡模式加入到Ingress資源中。

還值得注意的是,盡管健康檢查不直接通過Ingress公開,但Kubernetes中存在并行概念,例如準(zhǔn)備探查,可以使你達(dá)成相同的最終結(jié)果。 請查看特定控制器的文檔,以了解他們?nèi)绾翁幚斫】禉z查。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Kubernetes是Google開源的容器集群管理系統(tǒng),其提供應(yīng)用部署、維護(hù)、 擴(kuò)展機(jī)制等功能,利用Kubern...
    devabel閱讀 6,519評(píng)論 0 13
  • 1、基礎(chǔ)架構(gòu) 1.1 Master Master節(jié)點(diǎn)上面主要由四個(gè)模塊組成:APIServer、scheduler...
    阿斯蒂芬2閱讀 11,141評(píng)論 0 44
  • 一、 K8s 是什么? Kubernetes(k8s)是自動(dòng)化容器操作的開源平臺(tái),這些操作包括部署,調(diào)度和節(jié)點(diǎn)集群...
    loveroot閱讀 6,708評(píng)論 1 21
  • kubernetes 簡介 一個(gè)迅速過一遍kubernetes 非常不錯(cuò)的資源:基于Kubernetes構(gòu)建Doc...
    bradyjoestar閱讀 15,355評(píng)論 2 7
  • 端午節(jié)注定是尋虐的日子,還記得去年的端午在沙漠中度過的,一個(gè)月前約定了跟天津翱翔戶外俱樂部來大五,直到出發(fā)前一個(gè)小...
    Vivian_wh閱讀 579評(píng)論 1 0

友情鏈接更多精彩內(nèi)容