首頁>技術>

服務

Kubernetes服務是一種為一組功能相同的pod提供單一不變的接入點的資源;當服務存在時,它的IP地址和埠不會改變,客戶端通過IP地址和埠號建立連線,這些連線會被路由到提供該服務的任意一個pod上;

1.建立服務

服務的連線對所有的後端pod是負載均衡的,至於哪些pod被屬於哪個服務,通過在定義服務的時候設定標籤選擇器;

[d:\\k8s]$ kubectl create -f kubia-rc.yamlreplicationcontroller/kubia created[d:\\k8s]$ kubectl get podNAME          READY   STATUS              RESTARTS   AGEkubia-6dxn7   0/1     ContainerCreating   0          4skubia-fhxht   0/1     ContainerCreating   0          4skubia-fpvc7   0/1     ContainerCreating   0          4s

使用之前的yaml檔案建立pod,模版中設定的標籤為app: kubia,所以建立服務的yaml(還有之前介紹的kubectl expose方式也可以建立服務)中也需要指定相同的標籤:

apiVersion: v1kind: Servicemetadata:  name: kubiaspec:  ports:  - port: 80    targetPort: 8080  selector:    app: kubia

首先指定的資源型別為Service,然後指定了兩個埠分別:port服務提供的埠,targetPort指定pod中程序監聽的埠,最後指定標籤選擇器,相同標籤的pod被當前服務管理;

[d:\\k8s]$ kubectl create -f kubia-svc.yamlservice/kubia created[d:\\k8s]$ kubectl get svcNAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGEkubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   6d15hkubia        ClusterIP   10.96.191.193   <none>        80/TCP    4s[d:\\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.191.193You've hit kubia-fhxht[d:\\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.191.193You've hit kubia-fpvc7

建立完服務之後,可以發現給kubia分配了CLUSTER-IP,這是一個內部ip;至於如何測試可以使用kubectl exec命令遠端地在一個已經存在的pod容器上執行任何命令;pod名稱可以隨意指定三個中的任何一個,接收到crul命令的pod,會轉發給Service,由Service來決定將請求交給哪個pod處理,所以可以看到多次執行,發現每次處理的pod都不一樣;如果希望特定客戶端產生的所有請求每次都指向同一個pod, 可以設定服務的sessionAffinity屬性為ClientIP;

1.1配置會話黏性
apiVersion: v1kind: Servicemetadata:  name: kubiaspec:  sessionAffinity: ClientIP  ports:  - port: 80    targetPort: 8080  selector:    app: kubia

除了添加了sessionAffinity: ClientIP,其他都一樣

[d:\\k8s]$ kubectl delete svc kubiaservice "kubia" deleted[d:\\k8s]$ kubectl create -f kubia-svc-client-ip-session-affinity.yamlservice/kubia created[d:\\k8s]$ kubectl get svcNAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGEkubernetes   ClusterIP   10.96.0.1     <none>        443/TCP   6d15hkubia        ClusterIP   10.96.51.99   <none>        80/TCP    25s[d:\\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.51.99You've hit kubia-fhxht[d:\\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.51.99You've hit kubia-fhxht
1.2 同一個服務暴露多個埠

如果pod監聽了兩個或者多個埠,那麼服務同樣可以暴露多個埠:

apiVersion: v1kind: Servicemetadata:  name: kubiaspec:  ports:  - name: http    port: 80    targetPort: 8080  - name: https    port: 443    targetPort: 8080  selector:    app: kubia

因為Node.js只監聽了8080一個埠,所以這裡在Service裡面配置兩個埠都指向同一個目標埠,看是否都能訪問:

[d:\\k8s]$ kubectl create -f kubia-svc-named-ports.yamlservice/kubia created[d:\\k8s]$ kubectl get svcNAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGEkubernetes   ClusterIP   10.96.0.1      <none>        443/TCP          6d18hkubia        ClusterIP   10.96.13.178   <none>        80/TCP,443/TCP   7s[d:\\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.13.178You've hit kubia-fpvc7[d:\\k8s]$ kubectl exec kubia-6dxn7 -- curl -s http://10.96.13.178:443You've hit kubia-fpvc7

可以發現使用兩個埠都可以訪問;

1.3 使用命名的埠

在Service中指定了埠為8080,如果目標埠變了這裡也需要改變,可以在定義pod的模版中給埠命名,在Service中可以直接指定名稱:

apiVersion: v1kind: Servicemetadata:  name: kubiaspec:  ports:  - port: 80    targetPort: http  selector:    app: kubia

targetPort直接使用了名稱http:

[d:\\k8s]$ kubectl create -f kubia-rc2.yamlreplicationcontroller/kubia created[d:\\k8s]$ kubectl get podNAME          READY   STATUS    RESTARTS   AGEkubia-4m9nv   1/1     Running   0          66skubia-bm6rx   1/1     Running   0          66skubia-dh87r   1/1     Running   0          66s[d:\\k8s]$ kubectl create -f kubia-svc2.yamlservice/kubia created[d:\\k8s]$ kubectl get svcNAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGEkubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   7dkubia        ClusterIP   10.96.106.37   <none>        80/TCP    10s[d:\\k8s]$ kubectl exec kubia-4m9nv -- curl -s http://10.96.106.37You've hit kubia-dh87r
2.服務發現

服務給我們提供了一個單一不變的ip去訪問pod,那是否每次都要先建立服務,然後找到服務的CLUSTER-IP,再給其他pod去使用;這樣就太麻煩了,Kubernets還提供了其他方式去訪問服務;

2.1 通過環境變數發現服務

在pod開始執行的時候,Kubernets會初始化一系列的環境變數指向現在存在的服務;如果建立的服務早於客戶端pod的建立,pod上的程序可以根據環境變數獲得服務的IP地址和埠號;

[d:\\k8s]$ kubectl get svcNAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGEkubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   7d14hkubia        ClusterIP   10.96.106.37   <none>        80/TCP    14h[d:\\k8s]$ kubectl get podNAME          READY   STATUS    RESTARTS   AGEkubia-4m9nv   1/1     Running   0          14hkubia-bm6rx   1/1     Running   0          14hkubia-dh87r   1/1     Running   0          14h[d:\\k8s]$ kubectl exec kubia-4m9nv envPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=kubia-4m9nvKUBERNETES_SERVICE_PORT_HTTPS=443KUBERNETES_PORT=tcp://10.96.0.1:443KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443KUBERNETES_PORT_443_TCP_PROTO=tcpKUBERNETES_PORT_443_TCP_PORT=443KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1KUBERNETES_SERVICE_HOST=10.96.0.1KUBERNETES_SERVICE_PORT=443NPM_CONFIG_LOGLEVEL=infoNODE_VERSION=7.10.1YARN_VERSION=0.24.4HOME=/root

因為這裡的pod早於服務的建立,所有沒有相關服務的相關資訊:

[d:\\k8s]$ kubectl delete po --allpod "kubia-4m9nv" deletedpod "kubia-bm6rx" deletedpod "kubia-dh87r" deleted[d:\\k8s]$ kubectl get podNAME          READY   STATUS    RESTARTS   AGEkubia-599v9   1/1     Running   0          48skubia-8s8j4   1/1     Running   0          48skubia-dm6kr   1/1     Running   0          48s[d:\\k8s]$ kubectl exec kubia-599v9 envPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=kubia-599v9...KUBIA_SERVICE_HOST=10.96.106.37KUBIA_SERVICE_PORT=80...

如果刪除pod重新建立新的pod,這樣服務就在建立pod之前了,再次獲取環境變數可以發現有KUBIA_SERVICE_HOST和KUBIA_SERVICE_PORT,分別代表了kubia服務的IP地址和埠號;這樣就可以通過環境變數去獲取IP和埠了;

2.2 通過DNS發現服務

名稱空間kube-system下有一個預設的服務kube-dns,其後端是一個coredns的pod:

[d:\\k8s]$ kubectl get svc --namespace kube-systemNAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGEkube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   9d[d:\\k8s]$ kubectl get po -o wide --namespace kube-systemNAME                               READY   STATUS    RESTARTS   AGE   IP               NODE       NOMINATED NODE   READINESS GATEScoredns-7f9c544f75-h2cwn           1/1     Running   0          9d    172.17.0.3       minikube   <none>           <none>coredns-7f9c544f75-x2ttk           1/1     Running   0          9d    172.17.0.2       minikube   <none>           <none>

執行在pod上的程序DNS查詢都會被Kubernets自身的DNS伺服器響應,該伺服器知道系統中執行的所有服務;客戶端的pod在知道服務名稱的情況下可以通過全限定域名(FQDN)來訪問

[d:\\k8s]$ kubectl exec kubia-599v9 -- curl -s http://kubia.default.svc.cluster.localYou've hit kubia-8s8j4

kubia對應服務名稱,default為服務所在的名稱空間,svc.cluster.local是在所有叢集本地服務名稱中使用的可配置叢集域字尾;如果兩個pod在同一個名稱空間下,可以省略svc.cluster.local和default,使用服務名即可:

[d:\\k8s]$ kubectl exec kubia-599v9 -- curl -s http://kubia.defaultYou've hit kubia-dm6kr[d:\\k8s]$ kubectl exec kubia-599v9 -- curl -s http://kubiaYou've hit kubia-dm6kr
2.3 在pod中執行shell
d:\\k8s>winpty kubectl exec -it kubia-599v9 -- sh# curl -s http://kubiaYou've hit kubia-dm6kr# exit

通過kubectl exec命令在一個pod容器上執行bash,這樣就無須為每個要執行的命令執行kubectl exec命令;因為在windows環境下使用了winpty工具;

連線叢集外部的服務

以上介紹的後端是叢集中執行的一個或多個pod的服務;但也存在希望通過Kubernetes服務特性暴露外部服務的情況,可以通過Endpoint方式和外部服務別名的方式;

1.Endpoint

服務並不是和pod直接相連的;有一種資源介於兩者之間:它就是Endpoint資源

[d:\\k8s]$ kubectl describe svc kubiaName:              kubiaNamespace:         defaultLabels:            <none>Annotations:       <none>Selector:          app=kubiaType:              ClusterIPIP:                10.96.106.37Port:              <unset>  80/TCPTargetPort:        http/TCPEndpoints:         172.17.0.10:8080,172.17.0.11:8080,172.17.0.9:8080Session Affinity:  NoneEvents:            <none>[d:\\k8s]$ kubectl get pod -o wideNAME          READY   STATUS    RESTARTS   AGE     IP            NODE       NOMINATED NODE   READINESS GATESkubia-599v9   1/1     Running   0          3h51m   172.17.0.10   minikube   <none>           <none>kubia-8s8j4   1/1     Running   0          3h51m   172.17.0.11   minikube   <none>           <none>kubia-dm6kr   1/1     Running   0          3h51m   172.17.0.9    minikube   <none>           <none>

可以看到Endpoints對應其實就是pod的IP和埠;當客戶端連線到服務時,服務代理選擇這些IP和埠對中的一個,並將傳入連線重定向到在該位置監聽的伺服器;

2.手動配置服務的endpoint(內部)

如果建立了不包含pod選擇器的服務,Kubernetes將不會建立Endpoint資源;這樣就需要建立Endpoint資源來指定該服務的Endpoint列表;

apiVersion: v1kind: Servicemetadata:  name: external-servicespec:  ports:  - port: 80

如上定義沒有指定selector選擇器:

[d:\\k8s]$ kubectl create -f external-service.yamlservice/external-service created[d:\\k8s]$ kubectl get svc external-serviceNAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGEexternal-service   ClusterIP   10.96.241.116   <none>        80/TCP    74s[d:\\k8s]$ kubectl describe svc external-serviceName:              external-serviceNamespace:         defaultLabels:            <none>Annotations:       <none>Selector:          <none>Type:              ClusterIPIP:                10.96.241.116Port:              <unset>  80/TCPTargetPort:        80/TCPEndpoints:         <none>Session Affinity:  NoneEvents:            <none>

可以發現因為沒有指定selector選擇器,external-service的Endpoints為none,這種情況可以手動配置服務的Endpoint;

apiVersion: v1kind: Endpointsmetadata:  name: external-servicesubsets:  - addresses:    - ip: 172.17.0.9    - ip: 172.17.0.10    ports:    - port: 8080

Endpoint物件需要與服務具有相同的名稱,幷包含該服務的目標IP地址和埠列表:

[d:\\k8s]$ kubectl create -f external-service-endpoints.yamlendpoints/external-service created[d:\\k8s]$ kubectl describe svc external-serviceName:              external-serviceNamespace:         defaultLabels:            <none>Annotations:       <none>Selector:          <none>Type:              ClusterIPIP:                10.96.241.116Port:              <unset>  80/TCPTargetPort:        80/TCPEndpoints:         172.17.0.10:8080,172.17.0.9:8080Session Affinity:  NoneEvents:            <none>[d:\\k8s]$ kubectl exec kubia-599v9 -- curl -s http://external-serviceYou've hit kubia-dm6kr

可以發現再建立完Endpoints之後,服務external-service的Endpoints中多了pod的ip地址和埠,同樣也可以通過kubectl exec執行請求;

3.手動配置服務的endpoint(外部)

以上在endpoint配置的是kubernetes內部的ip埠,同樣也可以配置外部的ip埠,在kubernetes外部啟動一個服務:

apiVersion: v1kind: Endpointsmetadata:  name: external-servicesubsets:  - addresses:    - ip: 10.13.82.21    ports:    - port: 8080

以上配置的10.13.82.21:8080就是一個普通的tomcat服務,在本機啟動即可

[d:\\k8s]$ kubectl create -f external-service-endpoints2.yamlendpoints/external-service created[d:\\k8s]$ kubectl create -f external-service.yamlservice/external-service created[d:\\k8s]$ kubectl exec kubia-599v9 -- curl -s http://external-serviceok

經測試可以返回外部服務的響應

[d:\\k8s]$ kubectl create -f external-service-externalname.yamlservice/external-service created[d:\\k8s]$ kubectl exec kubia-599v9 -- curl -s http://external-service:8080ok

經測試可以返回外部服務的響應

將服務暴露給外部客戶端

向外部公開某些服務,kubernetes提供了三種方式:NodePort服務,LoadBalance服務以及Ingress資源方式,下面分別介紹及實戰;

1.NodePort型別的服務

建立一個服務並將其型別設定為NodePort,通過建立NodePort服務,可以讓kubernetes在其所有節點上保留一個埠(所有節點上都使用相同的埠號),然後將傳入的連線轉發給pod;

apiVersion: v1kind: Servicemetadata:  name: kubia-nodeportspec:  type: NodePort  ports:  - port: 80    targetPort: 8080    nodePort: 30123  selector:    app: kubia

指定服務型別為NodePort,節點埠為30123;

d:\\k8s]$ kubectl create -f kubia-svc-nodeport.yamlservice/kubia-nodeport created[d:\\k8s]$ kubectl get svcNAME             TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGEkubernetes       ClusterIP   10.96.0.1     <none>        443/TCP        31dkubia-nodeport   NodePort    10.96.59.16   <none>        80:30123/TCP   3s[d:\\k8s]$ kubectl exec kubia-7fs6m -- curl -s http://10.96.59.16You've hit kubia-m487j

要外部可以訪問內部pod服務,需要知道節點的IP,我們這裡使用的節點為minikube,因為這裡的minikube是安裝在本地windows系統下,可以直接使用minikube的內部ip進行訪問

2.LoadBalance型別服務

相比NodePort方式可以通過任何節點的30312埠訪問內部的pod,LoadBalance方式擁有自己獨一無二的可公開訪問的IP地址;LoadBalance其實是NodePort的一種擴充套件,使得服務可以通過一個專用的負載均衡器來訪問;

apiVersion: v1kind: Servicemetadata:  name: kubia-loadbalancerspec:  type: LoadBalancer  ports:  - port: 80    targetPort: 8080  selector:    app: kubia

指定服務型別為LoadBalancer,無需指定節點埠;

d:\\k8s]$ kubectl create -f kubia-svc-loadbalancer.yamlservice/kubia-loadbalancer created[d:\\k8s]$ kubectl get svcNAME                 TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGEkubernetes           ClusterIP      10.96.0.1       <none>        443/TCP        31dkubia-loadbalancer   LoadBalancer   10.96.207.113   <pending>     80:30038/TCP   7skubia-nodeport       NodePort       10.96.59.16     <none>        80:30123/TCP   32m

可以看到雖然我們沒有指定節點埠,但是建立完之後自動啟動了30038節點埠

所以可以發現同樣能通過使用NodePort的方式來訪問服務(節點IP+節點埠);同時也可以通過EXTERNAL-IP來訪問,但是使用Minikube,就不會有外部IP地址,外部IP地址將會一直是pending狀態;

3.了解並防止不必要的網路跳數

當外部客戶端通過節點埠連線到服務時,隨機選擇的pod並不一定在接收連線的同一節點上執行;可以通過將服務配置為僅將外部通訊重定向到接收連線的節點上執行的pod來阻止此額外跳數;

apiVersion: v1kind: Servicemetadata:  name: kubia-nodeport-onlylocalspec:  type: NodePort  externalTrafficPolicy: Local  ports:  - port: 80    targetPort: 8080    nodePort: 30124  selector:    app: kubia

通過在服務的spec部分中設定externalTrafficPolicy欄位來完成;

4.Ingress型別服務

每個LoadBalancer服務都需要自己的負載均衡器,以及獨有的公有IP地址;而Ingress 只需要一個公網IP就能為許多服務提供訪問;當客戶端向Ingress傳送HTTP請求時,Ingress會根據請求的主機名和路徑轉發到對應的服務;

4.1 Ingress控制器

只有Ingress控制器在叢集中執行,Ingress資源才能正常工作;不同的Kubernetes環境使用不同的控制器實現,但有些並不提供預設控制器;我這裡使用的Minikube需要啟用附加元件才可以使用控制器;

[d:\\Program Files\\Kubernetes\\Minikube]$ minikube addons list- addon-manager: enabled- dashboard: enabled- default-storageclass: enabled- efk: disabled- freshpod: disabled- gvisor: disabled- helm-tiller: disabled- ingress: disabled- ingress-dns: disabled- logviewer: disabled- metrics-server: disabled- nvidia-driver-installer: disabled- nvidia-gpu-device-plugin: disabled- registry: disabled- registry-creds: disabled- storage-provisioner: enabled- storage-provisioner-gluster: disabled

列出所有的附件元件,可以看到ingress是不可用的,所以需要開啟

[d:\\Program Files\\Kubernetes\\Minikube]$ minikube addons enable ingress* ingress was successfully enabled

啟動之後可以檢視kube-system名稱空間下的pod

[d:\\k8s]$ kubectl get pods -n kube-systemNAME                                        READY   STATUS              RESTARTS   AGEcoredns-7f9c544f75-h2cwn                    1/1     Running             0          55dcoredns-7f9c544f75-x2ttk                    1/1     Running             0          55detcd-minikube                               1/1     Running             0          55dkube-addon-manager-minikube                 1/1     Running             0          55dkube-apiserver-minikube                     1/1     Running             0          55dkube-controller-manager-minikube            1/1     Running             2          55dkube-proxy-xtbc4                            1/1     Running             0          55dkube-scheduler-minikube                     1/1     Running             2          55dnginx-ingress-controller-6fc5bcc8c9-nvcb5   0/1     ContainerCreating   0          8sstorage-provisioner                         1/1     Running             0          55d

可以發現正在建立一個名稱為nginx-ingress-controller的pod,會一直停留在拉取映象狀態,並顯示如下錯誤:

Failed to pullimage"quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1": rpcerror: code = Unknown desc =contextcanceled

這是因為國內無法下載quay.io下面的映象,可以使用阿里雲映象:

image:registry.aliyuncs.com/google_containers/nginx-ingress-controller:0.26.1

可以從ingress-nginx下的deploy/static/mandatory.yaml檔案修改其中的映象為阿里雲映象,然後重新建立即可:

[d:\\k8s]$ kubectl create -f mandatory.yamlnamespace/ingress-nginx createdconfigmap/nginx-configuration createdconfigmap/tcp-services createdconfigmap/udp-services createdserviceaccount/nginx-ingress-serviceaccount createdclusterrole.rbac.authorization.k8s.io/nginx-ingress-clusterrole createdrole.rbac.authorization.k8s.io/nginx-ingress-role createdrolebinding.rbac.authorization.k8s.io/nginx-ingress-role-nisa-binding createdclusterrolebinding.rbac.authorization.k8s.io/nginx-ingress-clusterrole-nisa-binding createddeployment.apps/nginx-ingress-controller created

再次檢視kube-system名稱空間下的pod

[d:\\k8s]$ kubectl get pods -n kube-systemNAME                                        READY   STATUS    RESTARTS   AGEcoredns-7f9c544f75-h2cwn                    1/1     Running   0          56dcoredns-7f9c544f75-x2ttk                    1/1     Running   0          56detcd-minikube                               1/1     Running   0          56dkube-addon-manager-minikube                 1/1     Running   0          56dkube-apiserver-minikube                     1/1     Running   0          56dkube-controller-manager-minikube            1/1     Running   2          56dkube-proxy-xtbc4                            1/1     Running   0          56dkube-scheduler-minikube                     1/1     Running   2          56dnginx-ingress-controller-6fc5bcc8c9-nvcb5   1/1     Running   0          10mstorage-provisioner                         1/1     Running   0          56d

nginx-ingress-controller已經為Running狀態,下面就可以使用Ingress資源了;

4.2 Ingress資源

Ingress控制器啟動之後,就可以建立Ingress資源了

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: kubiaspec:  rules:  - host: kubia.example.com    http:      paths:      - path: /        backend:          serviceName: kubia-nodeport          servicePort: 80

指定資源型別為Ingress,定一個單一規則,所有傳送kubia.example.com的請求都會被轉發給埠為80的kubia-nodeport服務上;

[d:\\k8s]$ kubectl get svcNAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGEkubernetes       ClusterIP   10.96.0.1       <none>        443/TCP        53dkubia-nodeport   NodePort    10.96.204.104   <none>        80:30123/TCP   21h[d:\\k8s]$ kubectl create -f kubia-ingress.yamlingress.extensions/kubia created[d:\\k8s]$ kubectl get ingressNAME    HOSTS               ADDRESS          PORTS   AGEkubia   kubia.example.com   192.168.99.108   80      6m4s

需要把域名對映到ADDRESS:192.168.99.108,修改hosts檔案即可,下面就可以直接用域名訪問了,最終請求會被轉發到kubia-nodeport服務

大致請求流程如下:瀏覽器中請求域名首先會查詢域名伺服器,然後DNS返回了控制器的IP地址;客戶端向控制器傳送請求並在頭部指定了kubia.example.com;然後控制器根據頭部資訊確定客戶端需要訪問哪個服務;然後通過服務關聯的Endpoint物件檢視pod IP,並將請求轉發給其中一個;

4.3 Ingress暴露多個服務

rules和paths是陣列,可以配置多個

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: kubia2spec:  rules:  - host: kubia.example.com    http:      paths:      - path: /v1        backend:          serviceName: kubia-nodeport          servicePort: 80      - path: /v2        backend:          serviceName: kubia-nodeport          servicePort: 80  - host: kubia2.example.com    http:      paths:      - path: /        backend:          serviceName: kubia-nodeport          servicePort: 80

配置了多個host和path,這裡為了方便映射了同樣服務;

[d:\\k8s]$ kubectl create -f kubia-ingress2.yamlingress.extensions/kubia2 created[d:\\k8s]$ kubectl get ingressNAME     HOSTS                                  ADDRESS          PORTS   AGEkubia    kubia.example.com                      192.168.99.108   80      41mkubia2   kubia.example.com,kubia2.example.com   192.168.99.108   80      15m

同樣需要配置host檔案,測試如下:

4.4 配置Ingress處理TLS傳輸

以上介紹的訊息都是基於Http協議,Https協議需要配置相關證書;客戶端建立到Ingress控制器的TLS連線時,控制器將終止TLS連線;客戶端與Ingress控制器之間是加密的,而Ingress控制器和pod之間沒有加密;要使控制器可以這樣,需要將證書和私鑰附加到Ingress中;

[root@localhost batck-job]# openssl genrsa -out tls.key 2048Generating RSA private key, 2048 bit long modulus..................................................................+++........................+++e is 65537 (0x10001)[root@localhost batck-job]# openssl req -new -x509 -key tls.key -out tls.cert -days 360 -subj /CN=kubia.example.com[root@localhost batck-job]# ll-rw-r--r--. 1 root root 1115 Feb 11 01:20 tls.cert-rw-r--r--. 1 root root 1679 Feb 11 01:20 tls.key

生成的兩個檔案建立secret

[d:\\k8s]$ kubectl create secret tls tls-secret --cert=tls.cert --key=tls.keysecret/tls-secret created

現在可以更新Ingress物件,以便它也接收kubia.example.com的HTTPS請求;

apiVersion: extensions/v1beta1kind: Ingressmetadata:  name: kubiaspec:  tls:  - hosts:     - kubia.example.com    secretName: tls-secret  rules:  - host: kubia.example.com    http:      paths:      - path: /        backend:          serviceName: kubia-nodeport          servicePort: 80

tls中指定相關證書

[d:\\k8s]$ kubectl apply -f kubia-ingress-tls.yamlWarning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl applyingress.extensions/kubia configured

通過瀏覽器訪問https協議,如下圖所示

Pod就緒訊號

只要pod的標籤和服務的pod選擇器想匹配,pod就可以作為服務的後端,但是如果pod沒有準備好,是不能處理請求的,這時候就需要就緒探針了,用來檢查pod是否已經準備好了,如果檢查成功就可以作為服務的後端處理訊息了;

1.就緒探針型別

就緒探針有三種類型分別:

Exec探針:執行程序的地方,容器的狀態由程序的退出狀態程式碼確認;Http get探針:向容器傳送HTTP GET請求,通過響應的HTTP狀態程式碼判斷容器是否準備好;Tcp socket探針:它開啟一個TCP連線到容器的指定埠,如果連線己建立,則認為容器己準備就緒。

kubernetes會週期性地呼叫探針,並根據就緒探針的結果採取行動。如果某個pod報告它尚未準備就緒,則會從該服務中刪除該pod。如果pod再次準備就緒,則重新新增pod;

2.向pod新增就行探針

編輯ReplicationController,修改pod模版新增就緒探針

[d:\\k8s]$ kubectl edit rc kubialibpng warning: iCCP: known incorrect sRGB profilereplicationcontroller/kubia edited[d:\\k8s]$ kubectl get podsNAME          READY   STATUS    RESTARTS   AGEkubia-7fs6m   1/1     Running   0          22dkubia-m487j   1/1     Running   0          22dkubia-q6z5w   1/1     Running   0          22d

編輯ReplicationController如下所示,新增readinessProbe

[d:\\k8s]$ kubectl delete pod kubia-m487jpod "kubia-m487j" deleted[d:\\k8s]$ kubectl get podsNAME          READY   STATUS    RESTARTS   AGEkubia-7fs6m   1/1     Running   0          22dkubia-cxz5v   0/1     Running   0          114skubia-q6z5w   1/1     Running   0          22d

刪除一個pod,馬上會建立一個帶有就緒探針的pod,可以發現長時間READY為0;

總結

本文首先介紹了服務的基本知識,如何建立服務發現服務;然後介紹了服務和pod直接的關聯器endpoint;最後重點介紹了將服務暴露給外部客戶端的三種方式。

參考

Kubernetes in Action

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 優雅停止 SpringBoot 服務的幾種方式