1,簡介
- Kubernetes 暴露服務的有三種方式,分別為 LoadBlancer Service、NodePort Service、Ingress。
- Kubernetes中為了實現服務實例間的負載均衡和不同服務間的服務發現,創造了Serivce對象,同時又為從集群外部訪問集群創建了Ingress對象。
1.1 NodePort 類型
- 如果設置 type 的值為 "NodePort",Kubernetes master 將從給定的配置范圍內(默認:30000-32767)分配端口,每個 Node 將從該端口(每個 Node 上的同一端口)代理到 Service。該端口將通過 Service 的 spec.ports[*].nodePort 字段被指定。
- 如果需要指定的端口號,可以配置 nodePort 的值,系統將分配這個端口,否則調用 API 將會失敗(比如,需要關心端口沖突的可能性)。
- 這可以讓開發人員自由地安裝他們自己的負載均衡器,並配置 Kubernetes 不能完全支持的環境參數,或者直接暴露一個或多個 Node 的 IP 地址。
- 需要注意的是,Service 將能夠通過
:spec.ports[ ].nodePort 和 spec.clusterIp:spec.ports[].port 而對外可見。 - NodePort Service 是通過在節點上暴漏端口,然后通過將端口映射到具體某個服務上來實現服務暴漏,比較直觀方便,但是對於集群來說,隨着 Service 的不斷增加,需要的端口越來越多,很容易出現端口沖突,而且不容易管理。當然對於小規模的集群服務,還是比較不錯的。
1.2 LoadBalancer 類型
- LoadBlancer Service 是 Kubernetes 結合雲平台的組件,如國外 GCE、AWS、國內阿里雲等等,使用它向使用的底層雲平台申請創建負載均衡器來實現,有局限性,對於使用雲平台的集群比較方便。
- 使用支持外部負載均衡器的雲提供商的服務,設置 type 的值為 "LoadBalancer",將為 Service 提供負載均衡器。 負載均衡器是異步創建的,關於被提供的負載均衡器的信息將會通過 Service 的 status.loadBalancer 字段被發布出去。
- 來自外部負載均衡器的流量將直接打到 backend Pod 上,不過實際它們是如何工作的,這要依賴於雲提供商。 在這些情況下,將根據用戶設置的 loadBalancerIP 來創建負載均衡器。 某些雲提供商允許設置 loadBalancerIP。如果沒有設置 loadBalancerIP,將會給負載均衡器指派一個臨時 IP。 如果設置了 loadBalancerIP,但雲提供商並不支持這種特性,那么設置的 loadBalancerIP 值將會被忽略掉。
1.3 Ingress 解析
- ingress就是從kubernetes集群外訪問集群的入口,將用戶的URL請求轉發到不同的service上。Ingress相當於nginx、apache等負載均衡方向代理服務器,其中還包括規則定義,即URL的路由信息,路由信息得的刷新由Ingress controller來提供。
- 通常情況下,service和pod的IP僅可在集群內部訪問。集群外部的請求需要通過負載均衡轉發到service在Node上暴露的NodePort上,然后再由kube-proxy將其轉發給相關的Pod。
- Ingress可以給service提供集群外部訪問的URL、負載均衡、SSL終止、HTTP路由等。為了配置這些Ingress規則,集群管理員需要部署一個Ingress controller,它監聽Ingress和service的變化,並根據規則配置負載均衡並提供訪問入口。
- Ingress Controller 實質上可以理解為是個監視器,Ingress Controller 通過不斷地跟 kubernetes API 打交道,實時的感知后端 service、pod 等變化,比如新增和減少 pod,service 增加與減少等;當得到這些變化信息后,Ingress Controller 再結合下文的 Ingress 生成配置,然后更新反向代理負載均衡器,並刷新其配置,達到服務發現的作用。
1.3.1 Nginx Ingress
- nginx-ingress 可以實現 7/4 層的代理功能(4 層代理基於 ConfigMap;7 層的Nginx反向代理) ,主要負責向外暴露服務,同時提供負載均衡等附加功能
- 反向代理負載均衡器,通常以Service的Port方式運行,接收並按照ingress定義的規則進行轉發,通常為nginx,haproxy,traefik等
- ingress是kubernetes的一個資源對象,用於編寫定義規則,通過它定義某個域名的請求過來之后轉發到集群中指定的 Service。它可以通過 Yaml 文件定義,可以給一個或多個 Service 定義一個或多個 Ingress 規則。
- Ingress Controller 可以理解為控制器,它通過不斷的跟 Kubernetes API 監聽交互,實時獲取后端 Service、Pod 等的變化,比如新增、刪除等,然后結合 Ingress 定義的規則生成配置,然后動態更新上邊的 Nginx 負載均衡器,並刷新使配置生效,來達到服務自動發現的作用。
- nginx-ingress 模塊在運行時主要包括三個主體:NginxController、Store、SyncQueue。
- Store 主要負責從 kubernetes APIServer 收集運行時信息,感知各類資源(如 ingress、service等)的變化,並及時將更新事件消息(event)寫入一個環形管道。
- SyncQueue 協程定期掃描 syncQueue 隊列,發現有任務就執行更新操作,即借助 Store 完成最新運行數據的拉取,然后根據一定的規則產生新的 nginx 配置,(有些更新必須 reload,就本地寫入新配置,執行 reload),然后執行動態更新操作,即構造 POST 數據,向本地 Nginx Lua 服務模塊發送 post 請求,實現配置更新。
- NginxController 作為中間的聯系者,監聽 updateChannel,一旦收到配置更新事件,就向同步隊列 syncQueue 里寫入一個更新請求。
2,部署 Nginx ingress
-
下載地址:https://github.com/kubernetes/ingress-nginx/archive/nginx-0.22.0.tar.gz
-
ingress-nginx文件位於deploy目錄下,各文件的作用:
- configmap.yaml:提供configmap可以在線更行nginx的配置,修改L4負載均衡配置的configmap
- namespace.yaml:創建一個獨立的命名空間 ingress-nginx
- rbac.yaml:創建對應的role rolebinding 用於rbac
- with-rbac.yaml:有應用rbac的nginx-ingress-controller組件
- mandatory.yaml:是其它組件yaml之和
2.1 修改 with-rbac.yaml 或者 mandatory.yaml
- kind: DaemonSet:官方原始文件使用的是deployment,replicate 為 1,這樣將會在某一台節點上啟動對應的nginx-ingress-controller pod。外部流量訪問至該節點,由該節點負載分擔至內部的service。測試環境考慮防止單點故障,改為DaemonSet然后刪掉replicate ,配合親和性部署在制定節點上啟動nginx-ingress-controller pod,確保有多個節點啟動nginx-ingress-controller pod,后續將這些節點加入到外部硬件負載均衡組實現高可用性。
- hostNetwork: true:添加該字段,暴露nginx-ingress-controller pod的服務端口(80)
- nodeSelector: 增加親和性部署,有custom/ingress-controller-ready 標簽的節點才會部署該DaemonSet
# with-rbac.yaml
apiVersion: apps/v1
# kind: Deployment
kind: DeamonSet
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
# replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
annotations:
prometheus.io/port: "10254"
prometheus.io/scrape: "true"
spec:
serviceAccountName: nginx-ingress-serviceaccount
hostNetwork: true
containers:
- name: nginx-ingress-controller
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.22.0
args:
- /nginx-ingress-controller
- --configmap=$(POD_NAMESPACE)/nginx-configuration
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services
- --publish-service=$(POD_NAMESPACE)/ingress-nginx
- --annotations-prefix=nginx.ingress.kubernetes.io
securityContext:
allowPrivilegeEscalation: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 33
runAsUser: 33
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- name: http
containerPort: 80
- name: https
containerPort: 443
livenessProbe:
failureThreshold: 3
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
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
nodeSelector:
custom/ingress-controller-ready: "true"
---
2.3 為需要部署nginx-ingress-controller的節點設置lable
kubectl label nodes 192.168.2.101 custom/ingress-controller-ready=true
kubectl label nodes 192.168.2.102 custom/ingress-controller-ready=true
kubectl label nodes 192.168.2.103 custom/ingress-controller-ready=true
2.4 創建 nginx-ingress
kubectl create -f mandatory.yaml
- 或
kubectl create -f configmap.yaml
kubectl create -f namespace.yaml
kubectl create -f rbac.yaml
kubectl create -f with-rbac.yaml
3,測試ingress
3.1 創建一個apache的Service
# cat > my-apache.yaml << EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-apache
spec:
replicas: 2
template:
metadata:
labels:
run: my-apache
spec:
containers:
- name: my-apache
image: httpd
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-apache
spec:
metadata:
labels:
run: my-apache
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30002
selector:
run: my-apache
EOF
3.2 創建一個 nginx 的Service
# cat > my-nginx.yaml << EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-nginx
spec:
template:
matadata:
lables:
run: my-nginx
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30001
selector:
run: my-nginx
EOF
3.3 配置ingress轉發文件
- host: 對應的域名
- path: url上下文
- backend:后向轉發 到對應的 serviceName: servicePort:
# cat > test-ingress.yaml << EOF
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test-ingress
namespace: default
spec:
rules:
- host: test.apache.ingress
http:
paths:
- path: /
backend:
serviceName: my-apache
servicePort: 80
- host: test.nginx.ingress
http:
paths:
- path: /
backend:
serviceName: my-nginx
servicePort: 80
EOF
3.4 查看狀態
# kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
test-ingress test.apache.ingress,test.nginx.ingress 80 23s
# kubectl get deploy,pod,svc
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deployment.extensions/my-apache 2 2 2 1 12s
deployment.extensions/my-nginx 2 2 2 2 12s
NAME READY STATUS RESTARTS AGE
pod/my-apache-57874fd49c-dc4vx 1/1 Running 0 12s
pod/my-apache-57874fd49c-lfhld 0/1 ContainerCreating 0 12s
pod/my-nginx-756f645cd7-fvq9d 1/1 Running 0 11s
pod/my-nginx-756f645cd7-ngj99 1/1 Running 0 12s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.254.0.1 <none> 443/TCP 10d
service/my-apache NodePort 10.254.95.131 <none> 80:30002/TCP 12s
service/my-nginx NodePort 10.254.92.19 <none> 80:30001/TCP 11s
3.5 解析域名到ipvs虛擬VIP,訪問測試
3.5.1 通過-H 指定模擬的域名
- test.apache.ingress
# curl -v http://192.168.2.100 -H 'host: test.apache.ingress'
* About to connect() to 192.168.2.100 port 80 (#0)
* Trying 192.168.2.100...
* Connected to 192.168.2.100 (192.168.2.100) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Accept: */*
> host: test.apache.ingress
>
< HTTP/1.1 200 OK
< Server: nginx/1.15.8
< Date: Fri, 25 Jan 2019 08:24:37 GMT
< Content-Type: text/html
< Content-Length: 45
< Connection: keep-alive
< Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT
< ETag: "2d-432a5e4a73a80"
< Accept-Ranges: bytes
<
<html><body><h1>It works!</h1></body></html>
* Connection #0 to host 192.168.2.100 left intact
- test.nginx.ingress
# curl -v http://192.168.2.100 -H 'host: test.nginx.ingress'
* About to connect() to 192.168.2.100 port 80 (#0)
* Trying 192.168.2.100...
* Connected to 192.168.2.100 (192.168.2.100) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Accept: */*
> host: test.nginx.ingress
>
< HTTP/1.1 200 OK
< Server: nginx/1.15.8
< Date: Fri, 25 Jan 2019 08:24:53 GMT
< Content-Type: text/html
< Content-Length: 612
< Connection: keep-alive
< Vary: Accept-Encoding
< Last-Modified: Tue, 25 Dec 2018 09:56:47 GMT
< ETag: "5c21fedf-264"
< Accept-Ranges: bytes
<
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
* Connection #0 to host 192.168.2.100 left intact
3.5.2 瀏覽器訪問




4,部署monitoring
4.1 配置 ingress
# cat > monitoring/prometheus-grafana-ingress.yaml << EOF
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: prometheus-grafana-ingress
namespace: ingress-nginx
spec:
rules:
- host: grafana.k8s.ing
http:
paths:
- path: /
backend:
serviceName: grafana
servicePort: 3000
- host: prometheus.k8s.ing
http:
paths:
- path: /
backend:
serviceName: prometheus-server
servicePort: 9090
EOF
4.2 在ingress-nginx官網deploy/monitoring目錄下載相關yaml文件
# ls monitoring/
configuration.yaml grafana.yaml prometheus-grafana-ingress.yaml prometheus.yaml
4.3 部署服務
# kubectl apply -f monitoring/
4.4 查看狀態
# kubectl get pod,svc,ingress -n ingress-nginx
NAME READY STATUS RESTARTS AGE
pod/grafana-5ccff7668d-7lk6q 1/1 Running 0 2d14h
pod/prometheus-server-7f87788f6-7zcfx 1/1 Running 0 2d14h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/glusterfs-dynamic-pvc-grafana ClusterIP 10.254.146.102 <none> 1/TCP 2d14h
service/glusterfs-dynamic-pvc-prometheus ClusterIP 10.254.160.58 <none> 1/TCP 2d14h
service/grafana NodePort 10.254.244.77 <none> 3000:30303/TCP 2d14h
service/prometheus-server NodePort 10.254.168.143 <none> 9090:32090/TCP 2d14h
NAME HOSTS ADDRESS PORTS AGE
ingress.extensions/prometheus-grafana-ingress grafana.k8s.ing,prometheus.k8s.ing 80 2d14h
4.5 配置grafana
- 解析打開頁面:http://grafana.k8s.ing



- 導入 json 文件
- 在ingress-nginx官網deploy/grafana/dashboards目錄下載相關nginx.json文件



