K8S原來如此簡單(四)Service+Ingress

chester·chen發表於2022-03-24

上一篇我們通過deployment實現了pod的橫向擴充套件,但是仍然不能負載,也不能對外提供服務,現在我們來看看如何通過k8s實現負載與外網訪問

Service

service為一組pod提供一個統一的入口,實現負載,也可實現外部訪問。

原理

 在Kubernetes叢集的每個Node上都會執行一個kube-proxy服務程式,kube-proxy會通過我們定義的service,自動生成iptables規則,這樣就能將到某個Service的訪問請求轉發到後端的多個Pod例項上。

Service型別

ClusterIP

通過叢集的內部 IP 暴露服務,選擇該模式時服務只能夠在叢集內部訪問。 這也是預設的 ServiceType。

 

NodePort

通過每個節點上的 IP 和靜態埠(NodePort)暴露服務。NodePort 服務會路由到自動建立的 ClusterIP 服務。 通過請求 <節點 IP>:<節點埠>,你可以從叢集的外部訪問一個 NodePort 服務。

LoadBalancer

使用雲提供商的負載均衡器向外部暴露服務。 外部負載均衡器可以將流量路由到自動建立的 NodePort 服務和 ClusterIP 服務上。

 

Service的Cluster IP與NodePort等概念是kube-proxy服務通過iptables 的NAT轉換實現的。kube-proxy在執行過程中動態建立與Service相關的 iptables規則,這些規則實現了將訪問服務(Cluster IP或NodePort)的請 求負載分發到後端Pod的功能。

 

kubeadm方式修改ipvs模式:

kubeadm方式修改ipvs模式:
kubectl edit configmap kube-proxy -n kube-system

...
mode: “ipvs“
...

定義Service

建立一個ClusterIP的service

apiVersion: v1
kind: Service
metadata:
  name: chesterservice
  namespace: chesterns
spec:
  selector:
    app: chesterapi
  ports:
    - protocol: TCP
      port: 5000
      targetPort: 5000

 

部署service,並通過service訪問oneapi

kubectl apply -f service.yaml
kubectl get service -n chesterns
kubectl describe service chesterservice -n chesterns
curl clusterip:5000/test

clusterip模式的service不能通過外網訪問,我們來定義一個nodeport模式的service,實現外部訪問

apiVersion: v1
kind: Service
metadata:
  name: chesterservice
  namespace: chesterns
spec:
  type: NodePort
  selector:
    app: chesterapi
  ports:
    - protocol: TCP
      port: 5000
      targetPort: 5000
      nodePort: 30111
kubectl delete -f service.yaml
kubectl apply -f service.yaml
kubectl get service -n chesterns
kubectl describe service chesterservice -n chesterns
curl nodeip:30111/test

 

服務發現

k8s通過兩種方式實現服務的發現

環境變數

當 Pod 執行在 Node 上,kubelet 會為每個活躍的 Service 新增一組環境變數

{SVCNAME}_SERVICE_HOST

{SVCNAME}_SERVICE_PORT

通過以下命令即可看到

kubectl get pod -n chesternskubectl exec chesterdeployment-6d89bc6b45-c5vbv  -n chesterns -- env
DNS

CoreDNS 是一種靈活的,可擴充套件的 DNS 伺服器,可以 安裝為叢集內的 Pod 提供 DNS 服務。

ClusterIP A記錄格式:

<service-name>.<namespace-name>.svc.cluster.local

示例:

my-svc.my-namespace.svc.cluster.local

Ingress

NodePort存在埠不足,只支援4層負載(IP:Port)不支援7層網路負載的缺點。Ingress為了彌補這些缺點而生。

對於基於HTTP的服務來說,不同的URL地址經常對應到不同的後端服務或者虛擬伺服器(Virtual Host),這些應用層的轉發機制僅通過Kubernetes的Service機制是無法實現的。

使用Ingress進行負載分發時,Ingress Controller基於Ingress規則將客戶端請求直接轉發到Service對應的後端Endpoint(Pod)上,這樣會跳過kube-proxy的轉發功能,kube-proxy不再起作用。如果Ingress Controller提供的是對外服務,則實際上實現的是邊緣路由器的功能。

 

 

Ingress Nginx

Ingress nginx是我們常用的一種ingress controller,他的原理是監聽Ingress資源,把使用者定義的Ingress轉移成Nginx的配置資訊

核心程式碼如下

 

安裝Ingress Nginx

通過以下連結下載yaml檔案:

https://kubernetes.github.io/ingress-nginx/deploy/

建立Ingress Controller

kubectl apply -f nginx-ingress.yamlkubectl get pods --namespace=ingress-nginx

建立Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: chesteringress
  namespace: chesterns
  annotations:
   kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: chester.k8s.com
    http:
      paths:
      - pathType: Prefix
        path: "/test"
        backend:
         service:
          name: chesterservice
          port:
           number: 5000

部署

kubectl apply -f ingress.yaml

檢視nginx配置資訊,判斷ingress是否生效

kubectl cp ingress-nginx-controller-58fccdc57c-gzkns:/etc/nginx/nginx.conf /tmp/nginx.conf -n ingress-nginx
cat /tmp/nginx.conf

配置hosts

kubectl get pods --namespace=ingress-nginx -o wide

vi /etc/hosts
(ingress-nginx-controller的叢集ip) chester.k8s.com

測試訪問

curl chester.k8s.com/test/

為Ingress配置https

配置HTTPS步驟:

  1. 準備域名證書檔案(來自:openssl/cfssl工具自籤或者權威機構頒發)

  2. 將證書檔案儲存到Secret

kubectl create secret tls chestertlssecret -- cert=chester.k8s.com.pem --key=chester.k8s.com-key.pem
  1. Ingress規則配置tls

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: chesteringress
spec:
 tls:
 - hosts:
   - chester.k8s.com
   secretName: chestertlssecret
 rules:
 - host: chester.k8s.com
   http:
    paths:
    - path: /
      pathType: Prefix
      backend:
       service:
        name: web
        port:
         number: 80

相關文章