Kubernetes(三) 如何從外部訪問服務
- 2019 年 12 月 20 日
- 筆記
.example_responsive_1 { width: 200px; height: 50px; } @media(min-width: 290px) { .example_responsive_1 { width: 270px; height: 50px; } } @media(min-width: 370px) { .example_responsive_1 { width: 339px; height: 50px; } } @media(min-width: 500px) { .example_responsive_1 { width: 468px; height: 50px; } } @media(min-width: 720px) { .example_responsive_1 { width: 655px; height: 50px; } } @media(min-width: 800px) { .example_responsive_1 { width: 728px; height: 50px; } } (adsbygoogle = window.adsbygoogle || []).push({});
Kubernetes(三) 如何從外部訪問服務
目錄
Kubernetes教程之對外暴露服務 文章地址: https://blog.piaoruiqing.com/2019/10/20/kubernetes-3-access-service/
前言
通過前文的講解,《跟著官方文檔從零搭建K8S》、《應用部署》相信讀者已經對Kubernetes安裝及部署應用有了一定的了解. 接下來, 本文將針對如何將服務暴露給外部進行講解.
閱讀這篇文章你能收穫到:
- 了解Kubernetes暴露服務的幾種方案及其優缺點.
閱讀本文你需要:
- 了解基本的Kubernetes命令.
- 有一個Kubernetes環境
將服務暴露給外部客戶端的幾種方式
- 通過
port-forward
轉發, 這種方式在之前的文章中有提到過, 操作方便、適合調試時使用, 不適用於生產環境. - 通過
NodePort
, 此時集群中每一個節點(Node)都會監聽指定埠, 我們通過任意節點的埠即可訪問到指定服務. 但過多的服務會開啟大量埠難以維護. - 通過
LoadBalance
來暴露服務.LoadBalance(負載均衡 LB)
通常由雲服務商提供, 如果雲環境中不提供LB服務, 我們通常直接使用Ingress
, 或使用MetalLB
來自行配置LB. - 通過
Ingress
公開多個服務.Ingress
公開了從群集外部到群集內services
的HTTP和HTTPS路由. 流量路由由Ingress
資源上定義的規則控制. 在雲服務商不提供LB服務的情況下, 我們可以直接使用Ingress
來暴露服務. (另外, 使用LB + Ingress
的部署方案可以避免過多LB應用帶來的花費).
準備
在開始之前, 筆者已經創建好了測試應用, 程式碼過長此處略去, 詳見附錄[1]和附錄[2]
我們通過kubectl get pods
查看pod列表.
指的一提的是, 我們可以通過
--namespace
參數查看指定命名空間的pod列表, 也可以通過--all-namespaces
來查看全部命名空間的pod列表. 由於沒有指定命名空間,所以應用被放到default
中了.
[root@nas-centos1 k8s-test]# kubectl get pods --namespace default NAME READY STATUS RESTARTS AGE k8s-test-578b77cd47-sw5pd 1/1 Running 0 6m29s k8s-test-578b77cd47-v6kmp 1/1 Running 0 6m29s
port-forward
port-forward
這種方式訪問pod, 可以指定pod實例, 簡單方便, 很適合調試之用.
通過kubectl port-forward
來配置轉發:
[root@nas-centos1 k8s-test]# kubectl port-forward --address 0.0.0.0 k8s-test-578b77cd47-sw5pd 9999:8080 Forwarding from 0.0.0.0:9999 -> 8080
此時, 我們可以通過通過訪問宿主機的9999
埠來訪問到k8s-test-578b77cd47-sw5pd
的8080
埠.
/k8s-test/timestamp
是該示例應用唯一一個api, 用於獲取當前時間戳
[root@nas-centos1 k8s-test]# curl http://10.33.30.95:9999/k8s-test/timestamp 1571151584224
[版權聲明] 本文發佈於朴瑞卿的部落格, 允許非商業用途轉載, 但轉載必須保留原作者朴瑞卿 及鏈接:https://blog.piaoruiqing.com. 如有授權方面的協商或合作, 請聯繫郵箱: [email protected].
NodePort
集群中每一個節點(Node)都會監聽指定埠, 我們通過任意節點的埠即可訪問到指定服務. 但過多的服務會開啟大量埠難以維護. 參考文檔: https://kubernetes.io/docs/concepts/services-networking/service/#nodeport
創建一個Service
, 並指定其類型為NodePort
.
k8s-test-service.yaml
apiVersion: v1 kind: Service metadata: name: k8s-test-service spec: selector: app: k8s-test env: test ports: - port: 80 # 服務埠, 內部可訪問 targetPort: 8080 # 目標埠, 此處指的是pod的8080埠 nodePort: 30080 # 節點埠, 外部可訪問 protocol: TCP type: NodePort
執行kubectl apply -f k8s-test-service.yaml
發布這個Service.
通過kubectl get services
可查看Service列表如下:
[root@nas-centos1 k8s-test]# kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE k8s-test-service NodePort 10.244.234.143 <none> 80:30080/TCP 8s kubernetes ClusterIP 10.244.0.1 <none> 443/TCP 32d
我們可以看到, 30080埠已經被綁定到該服務的80埠.
嘗試通過node節點來訪問應用:
[root@nas-centos3 ~]# curl http://10.33.30.94:30080/k8s-test/timestamp 1571152525336
LoadBalance
參考文檔:
- https://metallb.universe.tf/
- https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer
LoadBalance(負載均衡 LB)
通常由雲服務商提供. 如果環境不支援LB, 那麼創建的LoadBalance將始終處於<pending>
狀態:
[root@nas-centos1 k8s-test]# kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE k8s-test-service LoadBalancer 10.244.29.126 <pending> 80:32681/TCP 13s kubernetes ClusterIP 10.244.0.1 <none> 443/TCP 33d
如果想要在本地開發環境測試LB, 我們可以選擇MetalLB. 它是一個負載均衡實現. 安裝方式此處不進行展開, 可參考官方文檔
當我們的環境支援LB時, 我們可以創建如下Service, 來暴露服務:
apiVersion: v1 kind: Service metadata: name: k8s-test-service spec: selector: app: k8s-test env: test ports: - port: 80 # 服務埠 targetPort: 8080 # 目標埠, 此處指的是pod的8080埠 protocol: TCP type: LoadBalancer
執行kubectl apply -f k8s-test-lb.yaml
命令發布配置. 此時可以查看到Service已經有了EXTERNAL-IP(10.33.30.2). 如下:
[root@nas-centos1 k8s-test]# kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE k8s-test-service LoadBalancer 10.244.151.128 10.33.30.2 80:31277/TCP 2s kubernetes ClusterIP 10.244.0.1 <none> 443/TCP 33d
嘗試通過LB的IP來訪問應用, 如下:
[root@nas-centos1 k8s-test]# curl http://10.33.30.2/k8s-test/timestamp 1571235898264
Ingress
Ingress
公開了從群集外部到群集內services
的HTTP和HTTPS路由. 流量路由由Ingress
資源上定義的規則控制. 參考文檔: https://kubernetes.github.io/ingress-nginx/deploy/
我們使用ingress controller的nginx實現來進行測試. 首先下載部署文件:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
編輯文件vim mandatory.yaml
, 加入以下內容:
template: spec: hostNetwork: true
-
hostNetwork
: 開啟hostNetwork, 可以使ingress綁定到主機的80和443埠. - 訪問ingress有多種方式, (1). 通過hostNetwork直接綁定到80和443埠, (2). 通過NodePort在Node上暴露埠(但這種方式只能綁定固定範圍的埠, 默認值 30000-32767), (3). 通過LoadBalance, 這種方式和NodePort其實都是通過Service來暴露, 只不過是Service的不同類型.
- mandatory.yaml中
template
只有一個, 很好找. (tips: 在vim中可以用/
進行查找). -
Ingress Controller
: 是一個反向代理程式, 它負責解析 Ingress 的反向代理規則. -
Ingress
: Ingress 是反向代理規則. 不要混淆Ingress Controller
和Ingress
的概念.
發布完成後, 我們創建一個Ingress
來測試, 內容如下:
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: test-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: /k8s-test spec: rules: - http: paths: - path: /k8s-test backend: serviceName: k8s-test-service servicePort: 80
嘗試訪問:
[root@nas-centos1 ingress]# curl http://10.33.30.94/k8s-test/timestamp 1571321623058
小結
通常地, 我們會考慮 LoadBalance
和Ingress
配合使用. 一方面是只是用LB會產生大量的花費, 另一方面大量的LB同樣會提高維護成本. 而LB配合Ingress使用, 通過不同的path來區分服務能達到很棒的效果. (這裡和通過Nginx來暴露多個服務的原理基本相同)
參考文獻
附錄
[1] Deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: k8s-test labels: app: k8s-test spec: replicas: 2 template: metadata: name: k8s-test labels: app: k8s-test env: test spec: containers: - name: k8s-test image: registry.cn-hangzhou.aliyuncs.com/piaoruiqing/k8s-test:0.0.1 imagePullPolicy: IfNotPresent ports: - name: http-port containerPort: 8080 imagePullSecrets: - name: docker-registry-secret restartPolicy: Always selector: matchLabels: app: k8s-test
[2] K8sTestApplication.java
/** * @author piaoruiqing * @description: k8s test * @date: 2019/09/22 10:01 * @since JDK 1.8 */ @RestController @RequestMapping(value = "/k8s-test") @SpringBootApplication public class K8sTestApplication { /** * get timestamp * @return */ @GetMapping(value = "/timestamp") public ResponseEntity<?> getTimestamp() { return ResponseEntity.ok(System.currentTimeMillis() + "n"); } public static void main(String[] args) { SpringApplication.run(K8sTestApplication.class, args); } }
推薦閱讀:
© 2019, 朴瑞卿.
[版權聲明] 本文發佈於朴瑞卿的部落格, 允許非商業用途轉載, 但轉載必須保留原作者朴瑞卿 及鏈接:https://blog.piaoruiqing.com. 如有授權方面的協商或合作, 請聯繫郵箱: [email protected].