Kubernetes學習筆記(四):服務

服務介紹

服務是一種爲一組相同功能的pod提供單一不變接入點的資源。當服務存在時,他的IP和端口不會改變。客戶端經過IP和端口創建鏈接,這些鏈接會被路由到任何一個pod上。如此,客戶端不須要知道每一個單獨提供服務的pod地址,這些pod也能夠隨時被建立、刪除。html

服務經過標籤選擇器決定選擇哪些pod。node

準備鏡像

首先要準備一個可以提供web服務的鏡像,做者將鏡像存儲到了阿里雲的鏡像倉庫。linux

web.go

監聽8000端口,接到請求輸出當前hostnamenginx

package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
)

func main()  {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		hostname,_ := os.Hostname();
		fmt.Fprintf(w,"this is %v\n",hostname)
	})
	log.Fatal(http.ListenAndServe(":8000",nil))
}

Dockerfile

多步驟構建,有關與此以及Dockerfile的文章請見:Docker學習筆記(三):Dockerfile及多步驟構建鏡像git

FROM golang:1.14-alpine
COPY goweb.go /src/
RUN CGO_ENABLED=0 GOOS=linux go build -o /bin/goweb /src/goweb.go

FROM alpine
COPY --from=0 /bin/goweb /usr/local/bin/
RUN apk add --no-cache curl
EXPOSE 8000
CMD ["/usr/local/bin/goweb"]

構建、測試、推送

構建完成github

-> [feifei@ffmac.local] [~/work/service] docker build -t registry.cn-hangzhou.aliyuncs.com/orzi/goweb .
Sending build context to Docker daemon  3.072kB
......
Successfully built 3db4b643ba0a
Successfully tagged registry.cn-hangzhou.aliyuncs.com/orzi/goweb:latest

運行鏡像,本地8001映射到容器的8000golang

-> [feifei@ffmac.local] [~] docker run --rm -d -p 8001:8000 registry.cn-hangzhou.aliyuncs.com/orzi/goweb
6241a412caeacfe5f025d20af154b2eba98555fcb2b2f55742154a9e6fa46817

請求本地的8001端口web

-> [feifei@ffmac.local] [~] curl http://localhost:8001
this is 6241a412caea

沒有問題,推送docker

-> [feifei@ffmac.local] [~] docker push registry.cn-hangzhou.aliyuncs.com/orzi/goweb
The push refers to repository [registry.cn-hangzhou.aliyuncs.com/orzi/goweb]
8c5325633e9a: Pushed
3e207b409db3: Pushed
latest: digest: sha256:2704d806836060237169ea59cfda238c50fc5e5881e15cb1230200b5c8b2f5a0 size: 739

建立服務

goweb-rs.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: goweb-rs
spec:
  replicas: 2
  selector:
    matchLabels:
      app: goweb
  template:
    metadata:
      labels:
        app: goweb
    spec:
      containers:
        - name: goweb
          image: registry.cn-hangzhou.aliyuncs.com/orzi/goweb
          ports:
            - containerPort: 8000

goweb-svc.yaml

apiVersion: v1
kind: Service
metadata:
  name: goweb-svc
spec:
  ports:
    - port: 80		# 服務的端口
      targetPort: 8000	# 服務將鏈接轉發到容器的端口
  selector:		# 匹配此選擇器的都屬於這個服務
    app: goweb

建立一個名爲goweb-svc的服務,它將在80端口接收請求並將鏈接路由到具備標籤app=goweb的pod的8000端口上。api

建立

-> [root@kube0.vm] [~] k create -f goweb-svc.yaml
service/goweb-svc created

-> [root@kube0.vm] [~] k create -f goweb-rs.yaml
replicaset.apps/goweb-rs created

-> [root@kube0.vm] [~] k get all
NAME                 READY   STATUS    RESTARTS   AGE
pod/goweb-rs-6n6fw   1/1     Running   0          14m
pod/goweb-rs-vkwqb   1/1     Running   0          14m

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/goweb-svc    ClusterIP   10.104.46.76   <none>        80/TCP    9s
service/kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   40h

NAME                       DESIRED   CURRENT   READY   AGE
replicaset.apps/goweb-rs   2         2         2       14m

kubectl exec

訪問服務能夠在集羣節點上直接訪問,如:

-> [root@kube0.vm] [~] curl http://10.104.46.76
this is goweb-rs-vkwqb
-> [root@kube0.vm] [~] curl http://10.104.46.76
this is goweb-rs-6n6fw

或者經過kubectl exec命令在已存在的pod上執行curl

-> [root@kube0.vm] [~] k exec goweb-rs-vkwqb -- curl -s http://10.104.46.76
this is goweb-rs-vkwqb
-> [root@kube0.vm] [~] k exec goweb-rs-vkwqb -- curl -s http://10.104.46.76
this is goweb-rs-6n6fw

雙橫槓表示kubectl命令項的結束,在此以後的是指要在pod內部執行的命令。這是爲了不異常和歧義,若是須要執行的指令中沒有橫槓,那麼能夠不用雙橫槓。

sessionAffinity

使用svc.spec.sessionAffinity設置會話親和性,默認是None。指定爲ClientIP會使來自同一個Client IP的請求轉發到同一個Pod上。
Kubernetes只支持這兩種親和性設置,不支持cookie,由於Kubernetes不在HTTP層面工做。服務處理TCP和UDP包,不關心其中的內容。

一個服務暴露多個端口

建立一個多端口服務時,必須給每一個端口指定名字。

爲服務指定多個端口

apiVersion: v1
kind: Service
metadata:
  name: goweb-svc
spec:
  ports:
    - name: http
      port: 80
      targetPort: 8000
    - name: https
      port: 443
      targetPort: 8443
  selector:
    app: goweb

使用命名的端口

使用方法是:在Pod(或其餘資源的Pod模板)的spec.containers.ports.name配置中指定端口名稱,而後Service中的spec.ports.targetPort引用。

使用命名端口的好處在於,當Pod更改端口號時,不會影響到Service,由於Service引用的是端口名。

Pod中指定端口名:

spec:
  containers:
    - name: goweb
      ports:
        - name: http	# 命名8000端口爲http
          containerPort: 8000
        - name: https	# 命名8443端口爲https
          containerPort: 8443

Service中引用:

apiVersion: v1
kind: Service
metadata:
  name: goweb-svc
spec:
  ports:
    - name: http	# 將80端口映射到容器中名爲http的端口
      port: 80
      targetPort: http
    - name: https	# 將443端口映射到容器中名爲https的端口
      port: 443
      targetPort: https
  selector:
    app: goweb

服務發現

經過環境變量發現服務

在容器中執行env,列出一部分結果。
服務名稱中的橫線被轉換爲下劃線,而且所有轉爲大寫

-> [root@kube0.vm] [~] k exec goweb-rs-hztlt env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=goweb-rs-hztlt
KUBERNETES_SERVICE_HOST=10.96.0.1
KUBERNETES_SERVICE_PORT=443
GOWEB_SVC_SERVICE_HOST=10.98.92.202
GOWEB_SVC_SERVICE_PORT=80
.........

經過DNS發現服務

Kubernetes集羣運行了一個名爲kube-dns的服務,提供DNS解析。

-> [root@kube0.vm] [~] k get svc -n kube-system
NAME       TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   2d17h

查看容器內的/etc/resolv.conf文件

-> [root@kube0.vm] [~] k exec goweb-rs-hztlt cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local lan vm
options ndots:5

沒有錯,nameserver指定的IP就是kube-dns服務的地址!

經過FQDN鏈接服務

FQDN(Fully Qualified Domain Name):全限定域名
好比:goweb-svc.default.svc.cluster.local,goweb-svc是Service名稱,default是命名空間,svc表示資源類型,cluster.local表示本地集羣后綴。

根據狀況,能夠省略命名空間(請求方與Service在相同命名空間下)和 svc.cluster.local,也就是說下列狀況都是能夠的:

-> [root@kube0.vm] [~] k exec goweb-rs-dknjv -- curl -s http://goweb-svc
this is goweb-rs-dknjv
-> [root@kube0.vm] [~] k exec goweb-rs-dknjv -- curl -s http://goweb-svc.default
-> [root@kube0.vm] [~] k exec goweb-rs-dknjv -- curl -s http://goweb-svc.default.svc.cluster.local

沒法ping通服務IP的緣由

由於服務的集羣IP是一個虛擬IP,而且只有在與服務端口結合時纔有意義。

Endpoint

Service與Pod不是直接相連的,有一種資源介於二者之間,他就是Endpoint。

Endpoint暴露一個服務的IP和端口列表。

查看Service

-> [root@kube0.vm] [~] k describe svc goweb-svc
Name:              goweb-svc
Namespace:         default
.......
Endpoints:         10.244.1.58:8000,10.244.2.61:8000
.......

查看Endpoint資源

-> [root@kube0.vm] [~] k get ep
NAME         ENDPOINTS                           AGE
goweb-svc    10.244.1.58:8000,10.244.2.61:8000   7h58m
kubernetes   192.168.199.117:6443                8h

手動配置服務的Endpoint

若是建立了不包含Pod選擇器的服務,Kubernetes將不會建立Endpoint資源。

建立沒有Pod選擇器的Service

external-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: external-svc
spec:
  ports:
    - port: 80

查看external-svc

-> [root@kube0.vm] [~] k describe svc external-svc
Name:              external-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          <none>
Type:              ClusterIP
IP:                10.108.251.192
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         <none>
Session Affinity:  None
Events:            <none>

爲沒有選擇器的服務建立Endpoint

Endpoint對象須要與服務具備相同的名字,幷包含該服務的目標IP和端口列表

Service和Endpoint都提交到服務器後,Service就又能夠像具備Pod選擇器那樣了。

external-service-endpoint.yaml

apiVersion: v1
kind: Endpoints
metadata:
  name: external-svc	# 名字必須與相應服務的名字相同
subsets:
  - addresses:		# IP、端口列表
    - ip: 11.11.11.11
    - ip: 22.22.22.22
    ports:
      - port: 80

建立Endpoint

-> [root@kube0.vm] [~] k create -f external-svc-endpoint.yaml
endpoints/external-svc created

查看external-svc服務

-> [root@kube0.vm] [~] k describe svc external-svc
Name:              external-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          <none>
Type:              ClusterIP
IP:                10.108.251.192
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         11.11.11.11:80,22.22.22.22:80
Session Affinity:  None
Events:            <none>

爲外部服務建立別名

建立一個具備別名的外部服務時,須要指定service.spec.type的值爲ExternalName;而且指定service.spec. externalName的值爲外部服務的完整域名。所以鏈接到服務的客戶端將直接鏈接到外部服務,徹底繞過服務代理。出於這個緣由,這些類型的服務也就沒有集羣IP

external-svc-externalname.yaml

apiVersion: v1
kind: Service
metadata:
  name: external-svc-externalname
spec:
  type: ExternalName		# 服務類型
  externalName: www.baidu.com	# 外部服務的完整域名
  ports:
  - port: 80

建立、查看別名外部服務,能夠看到external-svc-externalname確實沒有集羣IP

-> [root@kube0.vm] [~] k create -f external-svc-externalname.yaml
service/external-svc-externalname created

-> [root@kube0.vm] [~] k get svc
NAME                        TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)   AGE
external-svc                ClusterIP      10.108.251.192   <none>          80/TCP    57m
external-svc-externalname   ExternalName   <none>           www.baidu.com   80/TCP    18s
kubernetes                  ClusterIP      10.96.0.1        <none>          443/TCP   9h

經過external-svc-externalname.default.svc.cluster.local甚至是external-svc-externalname能夠訪問服務。

NodePort與LoadBalancer

如下幾種方式可在外部訪問服務:

  • 將服務的類型設置成NodePort:
    每一個集羣節點都會打開一個相同的端口,並將該端口的流量重定向到服務。
  • 將服務的類型設置成LoadBalancer:
    LoadBalancer是NodePort的一種擴展,這種類型須要雲基礎設施提供專用的負載均衡器,負載均衡器將流量轉發到集羣的節點端口。
    若是不支持LoadBalancer,那麼它會變得和NodePort同樣。
  • 建立一個Ingress資源:
    經過一個IP地址公開多個服務,它運行在第七層。

NodePort

goweb-nodeport.yaml

apiVersion: v1
kind: Service
metadata:
  name: goweb-nodeport
spec:
  type: NodePort	# Service類型
  ports:
    - port: 80		# Service的端口
      targetPort: 8000	# Pod的端口
      nodePort: 31234	# 經過任意Node的此端口訪問服務
  selector:
    app: goweb

建立、查看這個類型爲NodePort的服務

-> [root@kube0.vm] [~] k create -f goweb-nodeport.yaml
service/goweb-nodeport created

-> [root@kube0.vm] [~] k get svc goweb-nodeport
NAME             TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
goweb-nodeport   NodePort   10.105.234.226   <none>        80:31234/TCP   10s

查看節點IP

-> [root@kube0.vm] [~] k get node -o wide
NAME       STATUS   ROLES    AGE    VERSION   INTERNAL-IP       EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION               CONTAINER-RUNTIME
kube0.vm   Ready    master   3d5h   v1.17.3   192.168.199.117   <none>        CentOS Linux 7 (Core)   5.6.14-1.el7.elrepo.x86_64   docker://19.3.6
kube1.vm   Ready    <none>   3d5h   v1.17.3   192.168.199.231   <none>        CentOS Linux 7 (Core)   5.6.14-1.el7.elrepo.x86_64   docker://19.3.6
kube2.vm   Ready    <none>   3d5h   v1.17.3   192.168.199.212   <none>        CentOS Linux 7 (Core)   5.6.14-1.el7.elrepo.x86_64   docker://19.3.6

使用不一樣節點IP訪問服務

-> [root@kube0.vm] [~] curl http://192.168.199.231:31234
this is goweb-rs-pbxvx
-> [root@kube0.vm] [~] curl http://192.168.199.212:31234
this is goweb-rs-6wc2f

搞個圖

LoadBalancer

goweb-loadbalancer.yaml

apiVersion: v1
kind: Service
metadata:
  name: goweb-loadbalancer
spec:
  type: LoadBalancer	# 更改了類型
  ports:		# 去掉了nodePort、隨機分配
    - port: 80
      targetPort: 8000
  selector:
    app: goweb

建立、查看這個類型爲LoadBalancer的服務

-> [root@kube0.vm] [~] k create -f goweb-loadbalancer.yaml
service/goweb-loadbalancer created

-> [root@kube0.vm] [~] k get svc goweb-loadbalancer
NAME                 TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
goweb-loadbalancer   LoadBalancer   10.106.251.246   <pending>     80:31141/TCP   21m

EXTERNAL-IP字段一直是<pending>,是做者的環境不支持LoadBalancer。退而求其次,將其做爲NodePort使用:

-> [root@kube0.vm] [~] curl http://192.168.199.212:31141
this is goweb-rs-pbxvx
-> [root@kube0.vm] [~] curl http://192.168.199.231:31141
this is goweb-rs-6wc2f

搞個圖

外部鏈接的特性

externalTrafficPolicy

sservice.spec.externalTrafficPolicy設置爲local,則服務代理會選擇運行本地的Pod。若是本地Node沒有Pod,則鏈接將掛起。

客戶端IP是不記錄的

節點端口接收到鏈接是,會對包的源地址進行轉換(SNAT),所以數據包的源IP將發生改變。

可是externalTrafficPolicy爲local的不會進行SNAT

Ingress

由於每一個LoadBalancer服務都須要本身的負載均衡器,以及獨有的共有IP地址。而Ingress只須要一個地址就能夠爲多個服務提供訪問。當客戶端向Ingress發送Http請求時,Ingress會根據請求的主機名和路徑決定請求轉發到那個服務。

部署Ingress控制器

只有Ingress控制器在集羣中運行,Ingress資源才能正常工做。因此咱們要先部署Ingress控制器,須要作的工做很是簡單:
進入ingress-nginx官網,複製粘貼如下內容,而後執行就能夠了。

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-0.32.0/deploy/static/provider/baremetal/deploy.yaml

這時候查看Namespace,會發現多出一個ingress-nginx,具體內容就不細述了。

-> [root@kube0.vm] [~] k get ns
NAME              STATUS   AGE
default           Active   3d15h
ingress-nginx     Active   15m
kube-node-lease   Active   3d15h
kube-public       Active   3d15h
kube-system       Active   3d15h

除此以外還要作個小改動,執行k edit -n ingress-nginx service/ingress-nginx-controller,在spec下添加工做節點的IP。出處請見官網

externalIPs:
  - 192.168.199.231
  - 192.168.199.212

而後刪除其管理的Pod,使其重建。

-> [root@kube0.vm] [~] k delete -n ingress-nginx pod/ingress-nginx-controller-f8d756996-8prk2
pod "ingress-nginx-controller-f8d756996-8prk2" deleted

goweb-ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: goweb-ingress
spec:
  rules:
  - host: www.goweb.com
    http:
      paths:
      - path: /
        backend:
          serviceName: goweb-svc
          servicePort: 80

建立、查看goweb-ingress

-> [root@kube0.vm] [~] k create -f goweb-ingress.yaml
ingress.extensions/goweb-ingress created

-> [root@kube0.vm] [~] k get ing
NAME            HOSTS           ADDRESS           PORTS   AGE
goweb-ingress   www.goweb.com   192.168.199.212   80      61s

在host文件中添加 192.168.199.212 www.goweb.com。而後訪問

-> [root@kube0.vm] [~] curl http://www.goweb.com
this is goweb-rs-mhvj4
-> [root@kube0.vm] [~] curl http://www.goweb.com
this is goweb-rs-88k9t

暴露多個服務

須要暴露多個服務,參照goweb-ingress.yaml:

  • 將多個服務映射到同一個域名只要在pahts下再配置一個path便可。
  • 將多個服務映射到不一樣域名則配置多個host便可。

Ingress工做原理

從表面上看請求的流程是:client->ingress->service->pod,但其實是client->ingress->pod。
在Ingress收到客戶端的請求後,會根據域名和路徑來肯定服務,經過與該服務關聯的Endpoint對象查看Pod IP,並將客戶端的請求轉發給其中一個pod。也就是說,請求不會轉發給服務,服務只是被用來選擇pod。

處理TLS傳輸

佔個位置,之後補上。

就緒探針

就緒探針(readinessProbe)的類型與存活探針(livenessProbe)同樣,請見此文它與存活探針的不一樣在於:若是容器未經過檢查,則不會被終止或從新啓動,但Pod會被從服務的Endpoint中移除,它確保了客戶端只與正常的Pod交互。

在衆多的微服務中存在不少依賴關係,被依賴服務只有在準備就緒後,才能接收請求。因此就緒探針務必要定義。

goweb-readiness.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: goweb-readiness
spec:
  replicas: 2
  selector:
    matchLabels:
      app: goweb
  template:
    metadata:
      labels:
        app: goweb
    spec:
      containers:
        - name: goweb
          image: registry.cn-hangzhou.aliyuncs.com/orzi/goweb
          ports:
            - name: http
              containerPort: 8000
          readinessProbe:
            exec:
              command: ["ls","/var/ready"]

運行查看goweb-readiness

建立以後等了一段時間,能夠看到兩個Pod都處於爲就緒狀態,goweb-svc的Endpoints也是空的。

-> [root@kube0.vm] [~] k create -f goweb-readiness.yaml
replicaset.apps/goweb-rs created

-> [root@kube0.vm] [~] k get po
NAME                    READY   STATUS    RESTARTS   AGE
goweb-readiness-9k9kv   0/1     Running   0          11s
goweb-readiness-x2gfb   0/1     Running   0          11s

-> [root@kube0.vm] [~] k describe svc goweb-svc
Port:              http  80/TCP
TargetPort:        http/TCP
Endpoints:
Session Affinity:  None
Events:            <none>

讓咱們來給 goweb-readiness-9k9kv 建立一個/var/ready文件,使其準備就緒。

-> [root@kube0.vm] [~] k exec goweb-readiness-9k9kv touch /var/ready

再來查看、能夠看到已經有一個Pod就緒了,Endpoints也有內容了。

-> [root@kube0.vm] [~] k get po
NAME                    READY   STATUS    RESTARTS   AGE
goweb-readiness-9k9kv   1/1     Running   0          89s
goweb-readiness-x2gfb   0/1     Running   0          89s

-> [root@kube0.vm] [~] k describe svc goweb-svc
Endpoints:         10.244.2.74:8000

headless

將服務的spec.clusterIP設置爲None會使服務成爲headless服務。它不會被分配集羣IP,DNS對其解析時就會返回Pod IP。

默認狀況下,DNS對headless服務名解析只會返回已經就緒的Pod的IP。

goweb-headless.yaml

apiVersion: v1
kind: Service
metadata:
  name: goweb-headless
spec:
  clusterIP: None
  ports:
    - name: http
      port: 80
      targetPort: 8000
  selector:
    app: goweb

建立、查看

ReplicaSet是使用前面的goweb-readiness.yaml建立的。

-> [root@kube0.vm] [~] k create -f goweb-headless.yaml
service/goweb-headless created

-> [root@kube0.vm] [~] k get all -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
pod/goweb-readiness-2jj49   0/1     Running   0          10m   10.244.2.4   kube2.vm   <none>           <none>
pod/goweb-readiness-5h5sg   0/1     Running   0          10m   10.244.1.5   kube1.vm   <none>           <none>

NAME                     TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE     SELECTOR
service/goweb-headless   ClusterIP   None         <none>        80/TCP    9m54s   app=goweb
service/kubernetes       ClusterIP   10.96.0.1    <none>        443/TCP   79m     <none>

NAME                              DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES                                         SELECTOR
replicaset.apps/goweb-readiness   2         2         1       10m   goweb        registry.cn-hangzhou.aliyuncs.com/orzi/goweb   app=goweb

使用nslookup解析goweb-headless,沒有返回任何Pod的IP,這是由於兩個Pod都未就緒。

-> [root@kube0.vm] [~] k exec goweb-readiness-2jj49 nslookup goweb-headless
Server:		10.96.0.10
Address:	10.96.0.10:53

** server can't find goweb-headless.default.svc.cluster.local: NXDOMAIN
** server can't find goweb-headless.svc.cluster.local: NXDOMAIN
........

爲goweb-readiness-2jj49建立/var/ready使其知足就緒條件

k exec goweb-readiness-2jj49 touch /var/ready

再使用nslookup查看,能夠看到返回了goweb-readiness-2jj49 的 IP

-> [root@kube0.vm] [~] k exec goweb-readiness-2jj49 nslookup goweb-headless
Server:		10.96.0.10
Address:	10.96.0.10:53
......
Name:	goweb-headless.default.svc.cluster.local
Address: 10.244.2.4
......

如法炮製,使另外一個Pod生效,就能看到兩個Pod的IP了

publishNotReadyAddresses

service.spec.publishNotReadyAddresses設置爲true,容許DNS解析headless服務是發現未就緒的Pod。

將goweb-readiness的Pod副本變成3個

-> [root@kube0.vm] [~] k scale --replicas=3 rs goweb-readiness
replicaset.apps/goweb-readiness scaled

-> [root@kube0.vm] [~] k get po -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
goweb-readiness-2jj49   1/1     Running   0          24m   10.244.2.4   kube2.vm   <none>           <none>
goweb-readiness-5h5sg   1/1     Running   0          24m   10.244.1.5   kube1.vm   <none>           <none>
goweb-readiness-jb74c   0/1     Running   0          31s   10.244.1.6   kube1.vm   <none>           <none>

而後編輯goweb-headless,寫入publishNotReadyAddresses: true

-> [root@kube0.vm] [~] k edit svc goweb-headless
service/goweb-headless edited

nslookup查看,雖然有未就緒的,但IP仍是全都返回了。

-> [root@kube0.vm] [~] k exec goweb-readiness-2jj49 nslookup goweb-headless
Server:		10.96.0.10
Address:	10.96.0.10:53

Name:	goweb-headless.default.svc.cluster.local
Address: 10.244.2.4
Name:	goweb-headless.default.svc.cluster.local
Address: 10.244.1.5
Name:	goweb-headless.default.svc.cluster.local
Address: 10.244.1.6

注意事項

  • 雙橫槓表示kubectl命令項的結束,在此以後的是指要在pod內部執行的命令
  • 建立一個多端口服務時,必須給每一個端口指定名字。
  • 服務的IP沒法ping通:由於服務的集羣IP是一個虛擬IP,而且只有在與服務端口結合時纔有意義。
  • sservice.spec.sessionAffinity設置會話親和性,默認爲None,能夠設置爲ClientIP
  • 建立ExternalService須要將spec.type設置爲ExternalName,此類服務只在DNS級別實施(爲服務建立了CNAME DNS),也所以不會得到集羣IP。
  • service.spec.externalTrafficPolicy設置爲local,則服務代理會選擇運行本地的Pod。若是本地Node沒有Pod,則鏈接將掛起。
  • service.spec.publishNotReadyAddresses設置爲true,容許DNS解析headless服務是發現未就緒的Pod。

小結

  • 服務是一種爲一組相同功能的pod提供單一不變接入點的資源
  • 建立了不包含Pod選擇器的服務,Kubernetes將不會建立Endpoints資源。
  • 服務對外暴露的方法:NodePort、LoadBalancer、Ingress
  • Ingress的的工做原理是:client->ingress->pod,而不是client->ingress->service->pod。
  • 就緒探針與存活探針:
    • 就緒探針:做用確保客戶端只與正常的Pod交互。若是檢查未經過,不會終止或重啓容器,但Pod會被從服務的Endpoint中移除。
    • 存活探針:做榮是讓集羣知道Pod是否正常運行。若是檢查未經過,則終止異常容器並從新啓動。
  • 一些概念:Service、Endpoint、對外暴露、就緒探針,服務發現。
相關文章
相關標籤/搜索