上一篇我們通過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步驟:
-
準備域名證書檔案(來自:openssl/cfssl工具自籤或者權威機構頒發)
-
將證書檔案儲存到Secret
kubectl create secret tls chestertlssecret -- cert=chester.k8s.com.pem --key=chester.k8s.com-key.pem
-
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