Kubernetes教程之對外暴露服務java
文章地址: blog.piaoruiqing.com/2019/10/20/…node
經過前文的講解,《跟着官方文檔從零搭建K8S》、《應用部署》相信讀者已經對Kubernetes安裝及部署應用有了必定的瞭解. 接下來, 本文將針對如何將服務暴露給外部進行講解.nginx
閱讀這篇文章你能收穫到:git
閱讀本文你須要:github
port-forward
轉發, 這種方式在以前的文章中有提到過, 操做方便、適合調試時使用, 不適用於生產環境.NodePort
, 此時集羣中每個節點(Node)都會監聽指定端口, 咱們經過任意節點的端口便可訪問到指定服務. 但過多的服務會開啓大量端口難以維護.LoadBalance
來暴露服務. LoadBalance(負載均衡 LB)
一般由雲服務商提供, 若是雲環境中不提供LB服務, 咱們一般直接使用Ingress
, 或使用MetalLB
來自行配置LB.Ingress
公開多個服務. Ingress
公開了從羣集外部到羣集內 services
的HTTP和HTTPS路由. 流量路由由Ingress
資源上定義的規則控制. 在雲服務商不提供LB服務的狀況下, 咱們能夠直接使用Ingress
來暴露服務. (另外, 使用LB + Ingress
的部署方案能夠避免過多LB應用帶來的花費).在開始以前, 筆者已經建立好了測試應用, 代碼過長此處略去, 詳見附錄[1]和附錄[2]docker
咱們經過kubectl get pods
查看pod列表.vim
指的一提的是, 咱們能夠經過
--namespace
參數查看指定命名空間的pod列表, 也能夠經過--all-namespaces
來查看所有命名空間的pod列表.centos因爲沒有指定命名空間,因此應用被放到
default
中了.api
[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
這種方式訪問pod, 能夠指定pod實例, 簡單方便, 很適合調試之用.bash
經過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 複製代碼
集羣中每個節點(Node)都會監聽指定端口, 咱們經過任意節點的端口便可訪問到指定服務. 但過多的服務會開啓大量端口難以維護.
建立一個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(負載均衡 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
公開了從羣集外部到羣集內services
的HTTP和HTTPS路由. 流量路由由Ingress
資源上定義的規則控制.
咱們使用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來暴露多個服務的原理基本相同)
若是這篇文章對您有幫助,請點個贊吧 ( ̄▽ ̄)"
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 複製代碼
/** * @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); } } 複製代碼
歡迎關注公衆號(代碼如詩):