Kubernetes Service配置資訊詳解
Service
是kubernetes
最核心的概念,通過建立Service
,可以為一組具有相同功能的容器應用提供一個統一的入口地址,並且將請求進行負載分發到後端的各個容器應用上。
Service
服務是一個虛擬概念,邏輯上代理後端pod
。眾所周知,pod
生命週期短,狀態不穩定,pod
異常後新生成的pod ip
會發生變化,之前pod
的訪問方式均不可達。通過service
對pod
做代理,service
有固定的ip
和port
,ip:port
組合自動關聯後端pod
,即使pod
發生改變,kubernetes
內部更新這組關聯關係,使得service
能夠匹配到新的pod
。這樣,通過service
提供的固定ip
pod
,以及pod
是否發生改變,大大提高了服務質量。如果pod
使用rc
建立了多個副本,那麼service
就能代理多個相同的pod
,通過kube-proxy
,實現負載均衡。
叢集中每個Node
節點都有一個元件kube-proxy
,實際上是為service
服務的,通過kube-proxy
,實現流量從service
到pod
的轉發,kube-proxy
也可以實現簡單的負載均衡功能。
kube-proxy
代理模式:userspace方式
。kube-proxy
在節點上為每一個服務建立一個臨時埠,service
的IP:port
過來的流量轉發到這個臨時埠上,kube-proxy
pod
,然後建立iptables
,把流量匯入這個pod
裡面。
Service定義詳解
yaml格式的Service定義檔案的完整內容:
apiVersion: v1
kind: Service
matadata:
name: string
namespace: string
labels:
- name: string
annotations:
- name: string
spec:
selector: []
type: string
clusterIP: string
sessionAffinity: string
ports:
- name: string
protocol: string
port: int
targetPort: int
nodePort: int
status:
loadBalancer:
ingress:
ip: string
hostname: string
負載分發策略
目前kubernetes提供了兩種負載分發策略:RoundRobin和SessionAffinity
RoundRobin:輪詢模式,即輪詢將請求轉發到後端的各個Pod上
SessionAffinity:基於客戶端IP地址進行會話保持的模式,第一次客戶端訪問後端某個Pod,之後的請求都轉發到這個Pod上
預設是RoundRobin模式
在某些場景中,開發人員希望自己控制負載均衡的策略,不使用Service提供的預設負載,kubernetes通過Headless Service的概念來實現。不給Service設定ClusterIP(無入口IP地址):
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
clusterIP: None
selector:
app: nginx
有時候,一個容器應用提供多個埠服務:
apiVersion: v1
kind: Service
metadata:
name: webapp
spec:
ports:
- port: 8080
targetPort: 8080
name: web
- port: 8005
targetPort: 8005
name: management
selector:
app: webapp
為不同的應用分配各自的埠。
另一個例子是兩個埠使用了不同的4層協議,即TCP或UDP
apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "KubeDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: 169.169.0.100
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
叢集外部訪問Pod或Service
為了讓外部客戶端可以訪問這些服務,可以將Pod或者Service的埠號對映到宿主主機,使得客戶端應用能夠通過物理機訪問容器應用。
將容器應用的埠號對映到物理機
通過設定容器級別的hostPort,將容器應用的埠號對映到物理機上:
pod-hostport.yaml:
apiVersion: v1
kind: Pod
metadata:
name: webapp
labels:
app: webapp
spec:
containers:
- name: webapp
image: tomcat
ports:
- containerPort: 8080
hostPort:8081
通過kubectl create建立這個Pod:
kubectl create -f pod-hostport.yaml
通過物理機的IP地址和8081埠號訪問Pod內的容器服務:
curl 10.0.11.151:8081
通過設定Pod級別的hostNetwork=true
通過設定Pod級別的hostNetwork=true,該Pod中所有容器的埠號都將被直接對映到物理機上,設定hostWork=true是需要注意,在容器的ports定義部分如果不指定hostPort,則預設hostPort等於containerPort,如果指定了hostPort,則hostPort必須等於containerPort的值。
pod-hostnetwork.yaml:
apiVersion: v1
kind: Pod
metadata:
name: webapp
labels:
app: webapp
spec:
hostNetwork: true
containers:
- name: webapp
image: tomcat
imagePullPolicy: Never
ports:
- containerPort: 8080
建立這個Pod:
kubectl create -f pod-hostnetwork.yaml
通過物理機的IP地址和8080埠訪問Pod的容器服務:
curl 10.0.11.151:8080
將Service的埠號對映到物理機
通過設定nodePort對映到物理機,同時設定Service的型別為NodePort:
webapp-svc-nodeport.yaml:
apiVersion: v1
kind: Service
metadata:
name: webapp
spec:
type: NodePort
ports:
- port: 8080
targetPort: 8080
nodePort: 8081
selector:
app: webapp
建立這個Service:
kubectl create -f webapp-svc-nodeport.yaml
通過物理機的IP和埠訪問:
curl 10.0.11.151:8081
如果訪問不通,檢視下物理機的防火牆設定。同樣,對該Service的訪問也將被負載分發到後端多個Pod上