Kubernetes Service 筆記
抽象圖小記
graph TD
subgraph Kubernetes Cluster
A[Service] --> N1[Nginx]
A --> |Endpoints|N2[Nginx]
A --> N3[Nginx]
A --> N4[Nginx]
APP -->|Access Service 訪問Virutal Server| A
subgraph Node1
N1
N2
end
subgraph Node2
N3
end
subgraph Node3
N4
APP
end
end
簡單記錄一下,在沒有 Service,有很多服務,要怎麼分享出去使用是一個重要的課題。
不可能在程式設定多個IP,Service 透過 Virtual IP做分享內部服務。
Virtual IP 主要是做備援(HA)機制。不是在做LB。但是K8S是會做SLB。可以看相關 keepalived,利用LVS+keepalived的主從模式實現http的高可用性_實用技巧_程式人生,不過我沒有實做過。
使用上會使用DNS,${service}.${namespade}.cluster.local
。
實現 VIP和 Endpoint 轉化,有:
- Iptable(預設)
- Userspace
- IPVS
切換方法,是透過 kube-proxy --proxy-mode
做切換。
Kubernates Service Type
- ClusterIP
- NodePort
- Loadbalancer
- ExternalName
- Headless
Kubernetes — Service Types Overview | by Ashish Patel | DevOps Mojo | Medium
ClusterIP
來源端必須屬於 Cluster 內部,內部是指「各節點與運行中的Pod」。
沒有指定type,預設是 clusterIP
1
2
3
4
5
6
7
8
9
10
11
|
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
|
範例參考: Service | Kubernetes
- Port 對外存取的port。
- targetPort pod上面的對外的 port
詳細可看:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#serviceport-v1-core
ServicePort v1 core裡面有寫詳細。
Kubernetes 元件處理 Service 流程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
kubectl run alpaca-prod \
--image=gcr.io/kuar-demo/kuard-amd64:blue \
--port=8000 \
--labels="ver=1,app=alpaca,env=prod"
# 用 expose 創建一個 service
kubectl expose pod alpaca-prod
# 這邊很有趣,看 kubectl describe svc alpaca-prod
# 裡面
# spec:
# clusterIP: 10.96.29.232
# ports:
# - port: 8000
# protocol: TCP
# targetPort: 8000
# selector:
# app: alpaca
# env: prod
# ver: "1"
#是用 selector 對應
kubectl get services -o wide
|
1
2
3
4
5
6
7
8
9
|
# 現在 kubectl run 產生 pod ,所以應該可以不用這段
# 這段是書寫的,之後改成 deployment 再嘗試
ALPACA_POD=$(kubectl get pods -l app=alpaca \
-o jsonpath='{.items[0].metadata.name}')
# $ALPACA_POD => alapaca-pod
kubectl port-forward $ALPACA_POD 48858:8080
# 執行完成可以用 localhost:48858 看到頁面
|
Cluster IP
Cluster IP 是虛擬 IP,通常會指定一個 DNS,通常 IP 不會更動,這樣就不會有 DNS 快取問題。
在 namespace ,我們只需要用 service 名稱連結 pod
Service DNS
用剛剛kubectl port-forward $ALPACA_POD 48858:8080
進去http://localhost:48858/
裡面的DNS QUERY
name 輸入 alpaca-prod
就可以找到
Debugging DNS Resolution | Kubernetes
alpaca-prod.default.svc.cluster.local
這邊可以看到 alpaca-prod
後面 default
是 namespace
可以在 dns 搜尋 alpaca-prod.default 查詢到東西
完整的alpaca-prod.default.svc.cluster.local
也可以查詢到
1
2
3
4
5
6
7
8
|
;; opcode: QUERY, status: NOERROR, id: 22467
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;alpaca-prod.default.svc.cluster.local. IN A
;; ANSWER SECTION:
alpaca-prod.default.svc.cluster.local. 30 IN A 10.99.141.81
|
Readiness Prob
1
|
kubectl edit deployment/alpaca-prod
|
由於這邊使用 pod 會有Forbidden: pod updates may not change fields other than
Kubernetes 對 Pod 的更新做了限制,除了更改 Pod 中容器(包括工作容器與初始化容器)的鏡像,以及 activeDeadlineSeconds (對 Job 類型的 Pod 定義失敗重試的最大時間), tolerations (Pod 對污點的容忍),修改其它部分將不會產生作用,如我們可以嘗試在前面 Pod 定義文檔 pod-test.yaml 中將宿主機端口 8081 改為 8082,重新執行 kubectl apply, 將提示如下錯誤,
參考:Kubernetes筆記(五):瞭解Pod(容器組) - 知乎
1
2
3
4
5
6
7
8
9
10
|
...
livenessProbe:
httpGet:
path: /
port: 80
httpHeaders: # 此處header無意義,僅作示例
- name: purpose
value: for-test
initialDelaySeconds: 2
periodSeconds: 5
|
這邊就先不仔細研究
用 endpoints 觀察
使用 endpint 是尋找 service 將流量發送到何處地方,這邊會抓所有pod IP收集。
1
|
kubectl get endpoints alpaca-prod --watch
|
NodePort
ClusterIP功能都有,除了內部訪問,主機外面的
對每個節點(node)IP都可以被訪問Pod。
port: port Mapping(VIP使用)
targetPort: Service 8080 to Pod :80
nodePort: Node Port 30123 to Pod :80
nodePort 範圍 default(30000~32767),可以用 --service-node-port-range
調整。
1
|
kubectl edit service alpaca-prod
|
TYPE 改成 NodeType
這個就跟 docker 設定 port 對外很像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
Name: alpaca-prod
Namespace: default
Labels: app=alpaca
env=prod
ver=1
Annotations: <none>
Selector: app=alpaca,env=prod,ver=1
Type: NodePort
IP Families: <none>
IP: 10.99.141.81
IPs: <none>
Port: <unset> 8000/TCP
TargetPort: 8000/TCP
NodePort: <unset> 30306/TCP
Endpoints: 10.244.0.6:8000
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
|
這邊注意,由於我們使用 Kind 做測試
使用 nodePort 發現怎麼連不到
後來我注意到 node ,不應該是指操作 kubectl 主機上 面
1
|
kubectl get node -o wide
|
但是對 node 主機上 port 還是連不到
1
|
ssh <ndoe_ip> -L 8080:localhost:30306
|
不過看來 kind 不支源使用 nodeport
在考慮之後用 vagrant 環境跑跑看
LoadBalancer
一般雲端內件有提供這個功能
但好像也能自己架
這邊就不嘗試
如何建構 Kubernetes loadbalancer – BROBRIDGE
[Day12] 實作 Kubernetes 裸機 Load Balancer Part2 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
Endpoint
創建 Service 會一同建立 Endpoint
詳細:[Kubernetes] Service Overview | 小信豬的原始部落
感覺是 Service 底層操作元件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
kubectl describle endpints alpaca-prod
# Name: alpaca-prod
# Namespace: default
# Labels: app=alpaca
# env=prod
# ver=1
# Annotations: <none>
# Subsets:
# Addresses: 10.244.0.6
# NotReadyAddresses: <none>
# Ports:
# Name Port Protocol
# ---- ---- --------
# <unset> 8000 TCP
# Events: <none>
|
1
2
3
4
5
|
kubectl get endpints alpaca-prod --watch
# NAME ENDPOINTS AGE
# alpaca-prod 10.244.0.6:8000 6d2h
# alpaca-prod <none> 6d2h <-- kubectl delete pods alpaca-prod
# alpaca-prod 10.244.0.7:8000 6d2h <-- kubectl run alpaca-prod --image=gcr.io/kuar-demo/kuard-amd64:blue --port=8080 --labels="ver=1,app=alpaca,env=prod"
|
建立 Service yaml
1
2
3
4
5
6
7
8
9
10
11
|
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376
|
簡單來說 Service 對印 selector 去抓含有 Label 的 Pod
kube-proxy
kube-proxy 每一台 node 主機上面都會有這個東西。
kube-proxy 會監測 service 和 endpoint 是否發生變化,會重寫該模組 iptables 規則。
詳細:
Cluster IP 環境變數
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
kubectl exec alpaca-prod -- env
# PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# HOSTNAME=alpaca-prod
# KUBERNETES_PORT_443_TCP_PROTO=tcp
# ALPACA_PROD_PORT_8000_TCP_PROTO=tcp
# KUBERNETES_SERVICE_HOST=10.96.0.1
# KUBERNETES_PORT=tcp://10.96.0.1:443
# KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
# ALPACA_PROD_PORT=tcp://10.99.141.81:8000
# ALPACA_PROD_PORT_8000_TCP_PORT=8000
# KUBERNETES_SERVICE_PORT_HTTPS=443
# KUBERNETES_PORT_443_TCP_PORT=443
# ALPACA_PROD_PORT_8000_TCP=tcp://10.99.141.81:8000
# ALPACA_PROD_PORT_8000_TCP_ADDR=10.99.141.81
# KUBERNETES_SERVICE_PORT=443
# KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
# ALPACA_PROD_SERVICE_HOST=10.99.141.81
# ALPACA_PROD_SERVICE_PORT=8000
|
清除所有建立物件
1
2
3
4
|
# 查看之前建立有app label 的 pods , services 狀態
kubectl get pods,services -l app
# 刪除 app label 物件
kubectl delete services,deployments,pods -l app
|