前言
本篇是Kubernetes第十篇,大家一定要把環境搭建起來,看是解決不了問題的,必須實戰。
Kubernetes系列文章:
-
Kubernetes介紹 -
Kubernetes環境搭建 -
Kubernetes-kubectl介紹 -
Kubernetes-Pod介紹(-) -
Kubernetes-Pod介紹(二)-生命周期 -
Kubernetes-Pod介紹(三)-Pod調度 -
Kubernetes-Pod介紹(四)-Deployment -
Kubernetes-Service介紹(一)-基本概念 -
Kubernetes-Service介紹(二)-服務發現
什么需要Ingress
Service是基於四層TCP和UDP協議轉發的,而Ingress可以基於七層的HTTP和HTTPS協議轉發,可以通過域名和路徑做到更細粒度的划分,如下圖所示:

Ingress請求過程
用戶請求首先到達Ingress Controller,Ingress Controller根據Ingress的路由規則,查找到對應的Service,進而通過Endpoint查詢到Pod的IP地址,然后將請求轉發給Pod。

Ingress與Ingress Controller
簡單來說,Ingress Controller是負責具體轉發的組件,通過各種方式將它暴露在集群入口,外部對集群的請求流量會先到Ingress Controller,而Ingress對象是用來告訴Ingress Controller該如何轉發請求,比如哪些域名哪些Path要轉發到哪些服務等等。
Ingress Controller
Ingress Controller並不是Kubernetes自帶的組件,實際上Ingress Controller只是一個統稱,用戶可以選擇不同的Ingress Controller實現,目前,由Kubernetes維護的Ingress Controller只有Google的GCE與Ingress Nginx兩個,其他還有很多第三方維護的Ingress Controller。但是不管哪一種Ingress Controller,實現的機制都基本一致,只是在具體配置上有差異。一般來說,Ingress Controller的形式都是一個Pod,里面跑着daemon程序和反向代理程序。daemon負責不斷監控集群的變化,根據Ingress對象生成配置並應用新配置到反向代理,比如Nginx Ingress就是動態生成Nginx配置,動態更新upstream,並在需要的時候重新加載應用新配置。
Ingress
Ingress是一個API對象,和其他對象一樣,通過yaml文件來配置。Ingress通過Http或Https暴露集群內部Service,給Service提供外部URL、負載均衡、SSL/TLS能力以及基於Host代理。
Ingress的部署
Deployment+LoadBalancer模式的Service
如果要把Ingress部署在公有雲,那可以選擇這種方式。用Deployment部署Ingress Controller,創建一個type為LoadBalancer的Service關聯這組Pod。大部分公有雲,都會為LoadBalancer的Service自動創建一個負載均衡器,通常還綁定了公網地址。只要把域名解析指向該地址,就實現了集群服務的對外暴露。此方案確定需要在公有雲上部署。

Deployment+NodePort模式的Service
使用Deployment模式部署Ingress Controller,並創建對應的服務,但是type為NodePort。這樣,Ingress就會暴露在集群節點ip的特定端口上。由於Nodeport暴露的端口是隨機端口,一般會在前面再搭建一套負載均衡器來轉發請求。該方式一般用於宿主機是相對固定IP地址。
缺點:
-
NodePort方式暴露Ingress雖然簡單方便,但是NodePort多了一層轉發,在請求量級很大時可能對性能會有一定影響; -
請求節點會是類似http://www.a.com:3008,其中3008是Ingress Nginx的svc暴露出來的Nodeport端口,看起來不太專業;

DaemonSet+HostNetwork+NodeSelector模式
使用DaemonSet結合Nodeselector來部署Ingress Controller到特定的Node上,然后使用HostNetwork直接把該Pod與宿主機Node的網絡打通,直接使用宿主機的80/433端口就能訪問服務。這時Ingress Controller所在的Node機器就是流量入口。
優點
該方式整個請求鏈路最簡單,性能相對NodePort減少一層轉發,因此性能更好;
缺點
由於直接利用宿主機節點的網絡和端口,一個Node只能部署一個Ingress Controller的pod;

部署實戰
關於版本問題需要注意以下幾點:
本篇采用ingress-nginx v1.0.0,最新版本 v1.0.0適用於 Kubernetes 版本 v1.19+ ;
Kubernetes-v1.22+ 需要使用 ingress-nginx>=1.0,因為 networking.k8s.io/v1beta 已經移除;
Deployment+NodePort模式
-
使用wget下載v1.0.0的deploy.yaml,該處可能由於網絡的原因下載不下來,大家可以在第二步下載我改好的文件;
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.0.0/deploy/static/provider/baremetal/deploy.yaml
-
接下來我們需要修改deploy.yaml里面的鏡像文件,由於k8s.gcr.io相關的鏡像國內都進行屏蔽了,這里我采用了從docker官方去下載相關的鏡像文件,需要將k8s.gcr.io/ingress-nginx/controller:v1.0.0和k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.0鏡像替換為willdockerhub/ingress-nginx-controller:v1.0.0和jettech/kube-webhook-certgen:v1.5.2,這里需要注意的是kube-webhook-certgen有兩處不要漏替換,此外需要在args處增加--watch-ingress-without-class=true配置,這里將修改好的文件v1.0.0-deploy.yaml上傳到網盤, 鏈接 提取碼: sksc ;


-
部署nginx-ingress-controller;
kubectl apply -f v1.0.0-deploy.yaml
-
檢查nginx-ingress-controller創建的情況,這個我們會發現該Service是一個NodePort類型,並且被隨機分配兩個端口,分別是32368和32577,后續我們就需要通過這個端口訪問改地址信息;
#查看相關pod狀態
kubectl get pods -n ingress-nginx -owide
#查看service
kubectl get service -n ingress-nginx

-
創建Deployment和Service,這里我們就是就使用之前的nginx-deployment.yaml和nginx-service.yaml;
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: backend
replicas: 3
template:
metadata:
labels:
app: backend
spec:
containers:
- name: nginx
image: nginx:latest
resources:
limits:
memory: "128Mi"
cpu: "128m"
ports:
- containerPort: 80
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
#定義后端pod標簽為app=backend
selector:
app: backend
ports:
#service端口號
- port: 80
#pod的端口號
targetPort: 80
kubectl apply -f nginx-service.yaml
kubectl apply -f nginx-nodeport-service.yaml
-
驗證Service創建情況,並且可以通過Service地址訪問相關服務;
#查看service狀況
kubectl get svc
#訪問服務
curl http://10.96.45.195
-
新建ingress策略nodeport-ingress.yaml,創建對應資源;
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nodeport-ingress
namespace: default
spec:
rules:
- host: aa.bb.cc
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: nginx-service
port:
number: 80
#創建ingress資源
kubectl apply -f nodeport-ingress.yaml
#檢查ingress資源
kubectl get ingress

-
檢查資源的訪問,這里使用nginx-ingress-controller暴露的端口32368訪問服務的信息;
#第一種方案可以在對應Node上設置host文件
echo '172.21.122.231 aa.bb.cc' >> /etc/hosts
curl aa.bb.cc:32368
#使用curl方式
curl -v http://172.21.122.231:32368 -H 'host: aa.bb.cc'

DaemonSet+HostNetwork+nodeSelector模式
-
清除資源;
kubectl delete -f v.1.0.0-deploy.yaml
kubectl delete -f nginx-nodeport-service.yaml
kubectl delete -f nodeport-ingress.yaml
-
給Node節點打標簽為ingress=nginx;
kubectl label nodes demo-work-1 ingress=nginx
-
編輯v1.0.0-deploy.yaml,找到deployment部分,將kind變為DaemonSet,nodeSelector節點選擇器變為ingress等於nginx,增加網絡為hostNetwork等於true,這里需要在args新增--watch-ingress-without-class,這樣ingress規則才能生效,這個是新版的以后不太一樣的地方, 鏈接提取碼: dbag;
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
helm.sh/chart: ingress-nginx-4.0.1
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/version: 1.0.0
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: controller
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
revisionHistoryLimit: 10
minReadySeconds: 0
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/component: controller
spec:
dnsPolicy: ClusterFirst
containers:
- name: controller
image: willdockerhub/ingress-nginx-controller:v1.0.0
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
exec:
command:
- /wait-shutdown
args:
- /nginx-ingress-controller
- --election-id=ingress-controller-leader
- --controller-class=k8s.io/ingress-nginx
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- --validating-webhook=:8443
- --validating-webhook-certificate=/usr/local/certificates/cert
- --validating-webhook-key=/usr/local/certificates/key
- --watch-ingress-without-class=true # 新增
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
runAsUser: 101
allowPrivilegeEscalation: true
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: LD_PRELOAD
value: /usr/local/lib/libmimalloc.so
livenessProbe:
failureThreshold: 5
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
ports:
- name: http
containerPort: 80
protocol: TCP
- name: https
containerPort: 443
protocol: TCP
- name: webhook
containerPort: 8443
protocol: TCP
volumeMounts:
- name: webhook-cert
mountPath: /usr/local/certificates/
readOnly: true
resources:
requests:
cpu: 100m
memory: 90Mi
nodeSelector:
ingress: nginx
hostNetwork: true
serviceAccountName: ingress-nginx
terminationGracePeriodSeconds: 300
volumes:
- name: webhook-cert
secret:
secretName: ingress-nginx-admission
-
部署和檢查ingress-nginx;
#部署ingress-nginx
kubectl apply -f v1.0.0-deploy.yaml
#查看相關pod狀態
kubectl get pods -n ingress-nginx -owide
#查看service
kubectl get service -n ingress-nginx
-
新建nginx-service.yaml,將方式改變為ClusterIP形式;
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
#定義后端pod標簽為app=backend
selector:
app: backend
ports:
#service端口號
- port: 80
#pod的端口號
targetPort: 80
-
創建nginx-service,並檢查資源情況;
#創建nginx-service
kubectl apply -f nginx-service.yaml
#檢查資源狀況
kubectl get svc
#資源的綁定情況
kubectl describe service nginx-service
#通過curl訪問
curl 10.96.53.148

-
創建hostnetwork-ingress.yaml文件;
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nodeport-ingress
namespace: default
spec:
rules:
- host: aa.bb.cc
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: nginx-service
port:
number: 80
-
創建ingress資源;
#創建ingress
kubectl apply -f hostnetwork-ingress.yaml
#檢查ingress資源
kubectl get ingress
-
檢查資源的訪問;
curl -v http://172.21.122.231 -H 'host: aa.bb.cc'

結束
歡迎大家點點關注,點點贊!