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 | apiVersion: v1 |
範例參考: 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 | kubectl run alpaca-prod \ |
1 | # 現在 kubectl run 產生 pod ,所以應該可以不用這段 |
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 | ;; opcode: QUERY, status: NOERROR, id: 22467 |
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 | ... |
這邊就先不仔細研究
用 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 | Name: alpaca-prod |
這邊注意,由於我們使用 Kind 做測試
使用 nodePort 發現怎麼連不到
後來我注意到 node ,不應該是指操作 kubectl 主機上 面
1 | kubectl get node -o wide |
但是對 node 主機上 port 還是連不到
1 | ssh <ndoe_ip> -L 8080:localhost:30306 |
不過看來 kind 不支源使用 nodeport
- docker - How to use NodePort with kind? - Stack Overflow
- nginx - Kubernetes NodePort not listening - Stack Overflow
在考慮之後用 vagrant 環境跑跑看
LoadBalancer
一般雲端內件有提供這個功能
但好像也能自己架
這邊就不嘗試
如何建構 Kubernetes loadbalancer – BROBRIDGE
[Day12] 實作 Kubernetes 裸機 Load Balancer Part2 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天
Endpoint
創建 Service 會一同建立 Endpoint
詳細:[Kubernetes] Service Overview | 小信豬的原始部落
感覺是 Service 底層操作元件
1 | kubectl describle endpints alpaca-prod |
1 | kubectl get endpints alpaca-prod --watch |
建立 Service yaml
1 | apiVersion: v1 |
簡單來說 Service 對印 selector 去抓含有 Label 的 Pod
kube-proxy
kube-proxy 每一台 node 主機上面都會有這個東西。
kube-proxy 會監測 service 和 endpoint 是否發生變化,會重寫該模組 iptables 規則。
詳細:
Cluster IP 環境變數
1 | kubectl exec alpaca-prod -- env |
清除所有建立物件
1 | # 查看之前建立有app label 的 pods , services 狀態 |