前言
之前介紹了Kubernetes副本機制,正是因為副本機制你的部署能自動保待執行,並且保持健康,無須任何手動干預;本文繼續介紹kubernetes的另一個強大的功能服務,在客戶端和pod之間提供一個服務層,提供了單一的接入點,更加方便客戶端使用pod。
服務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: ReplicationControllermetadata: name: kubiaspec: replicas: 3 selector: app: kubia template: metadata: labels: app: kubia spec: containers: - name: kubia image: ksfzhaohui/kubia ports: - name: http containerPort: 8080
在之前的ReplicationController中稍作修改,在port是中指定了名稱,Service的yaml檔案同樣做修改,直接使用名稱:
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中執行shelld:\\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
經測試可以返回外部服務的響應
4.建立外部服務別名除了手動配置服務的Endpoint來代替公開外部服務方法,還可以通過給外部服務指定一個別名,比如給10.13.82.21指定一個域名:api.ksfzhaohui.com
apiVersion: v1kind: Servicemetadata: name: external-servicespec: type: ExternalName externalName: api.ksfzhaohui.com ports: - port: 80
要建立一個具有別名的外部服務的服務時,要將建立服務資源的一個type欄位設定為ExternalName;在externalName中指定外服服務的域名:
[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進行訪問
d:\\k8s]$ kubectl get nodes -o wideNAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIMEminikube Ready master 34d v1.17.0 192.168.99.108 <none> Buildroot 2019.02.7 4.19.81 docker://19.3.5image.png
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 pull image "quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.26.1": rpc error: code = Unknown desc = context canceled
這是因為國內無法下載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
apiVersion: v1kind: ReplicationControllermetadata: name: kubiaspec: replicas: 3 selector: app: kubia template: metadata: labels: app: kubia spec: containers: - name: kubia image: ksfzhaohui/kubia ports: - containerPort: 8080 readinessProbe: exec: command: - ls - /var/ready
就緒探針將定期在容器內執行ls/var/ready命令。如果檔案存在,則ls命令返回退出碼 0, 否則返回非零的退出碼;如果檔案存在,則就緒探針將成功,否則失敗;我們編輯完ReplicationController還沒有產生新的pod所以可以發現以上pod的READY都為1,表示已經準備好可以處理訊息;
[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;
原文來自:/file/2020/08/19/20200819181834_1615.jpg 儲存卷:容器服務在單節點的儲存組織形式,關注資料儲存、容器執行時的相關技術;K8s 儲存卷:關注容器叢集的儲存編排,從應用使用儲存的角度關注儲存服務。
其中,docker只是解決服務下層的問題,服務上層建築如容器編排,服務發現等問題已經超越了docker的管轄。kubernetes應運而生了。
Kubernetes提供的編排和管理功能,輕鬆完成大規模容器部署,藉助k8s的編排功能,使用者可以構建跨多個容器的應用服務,實現跨叢集排程,擴充套件容器,以及長期持續管理這些容器的健康狀況等,並整合網路,儲存,安全性,監控及其他服務,提供全面的容器基礎架構。
如果你想進一步了解K8s與雲原生相關知識,強烈推薦你閱讀 ↓↓
上下滾動檢視更多
哪些人適合閱讀本書
電腦科學、軟體工程等領域的軟體工程師和大學生使用/嘗試使用容器和Kubernetes技術的應用程式開發者希望理解雲原生技術棧基本原理的技術管理者和開發者具有基本伺服器端知識、正在探索容器技術的軟體開發者和技術管理者通過本書你將會系統掌握
Kubernetes 核心概念理解 Pod 和容器設計模式應用編排與管理:核心原理應用編排與管理:Deployment應用編排與管理Job 和 DaemonSet應用配置管理應用儲存和持久化資料卷Kubernetes網路概念及策略控制Kubernetes Services