【APP】為Kubernetes叢集中服務部署Nginx入口服務
這段日子,一直在搞與Kubernetes有關的東東:像什麼Kubernetes叢集搭建、DNS外掛安裝和配置、整合Ceph RBD持久卷、Private Registry映象庫訪問等,這些都緣於正在開發的一個類PaaS小平臺的需要:“平臺雖小,五臟俱全”。整個平臺由Kubernetes叢集承載,對於K8s叢集內部的Service來說,目前還欠缺一個服務入口。之前的《Kubernetes叢集中的Nginx配置熱更新方案》一文實際上就是入口方案設計的一個前奏,而本文則是說明一下Nginx入口服務部署設計和實施過程中遇到的一些坑。
一、Nginx入口方案簡述
Nginx作為叢集入口服務,從功能上說,一般都是充當反向代理和負載均衡的角色。在我們這裡它更多是用於反向代理,因為負載均衡的事情“移交”給了K8s去實現了。k8s通過ClusterIP- 一種VIP機制,預設基於iptables的負載分擔實現服務請求的負載均衡(如iptable nat table的規則:-m statistic –mode random –probability 0.33332999982),檢視iptables nat鏈的rules,可以看到如下樣例:
# iptables -t nat -nL
... ...
Chain KUBE-SVC-UQG6736T32JE3S7H (2 references)
target prot opt source destination
KUBE-SEP-Z7UQLD332S673VAF all -- 0.0.0.0/0 0.0.0.0/0 /* default/nginx-kit: */ statistic mode random probability 0.50000000000
KUBE-SEP-TWOIACCAJCPK3HWO all -- 0.0.0.0/0 0.0.0.0/0 /* default/nginx-kit: */
... ..
接下來,我們簡單說說我們的Nginx入口方案。事先宣告:這絕對不是一個理想的方案,因為它還有諸多缺陷,只是在目前平臺需求上下文和資源的約束前提下,它可以作為我們的一個可用的過渡方案,方案示意圖如下:
- Nginx以Kubernetes service的形式執行於K8s cluster內部,並限制只能被K8s排程到帶有label: role=entry的Node上;
- 最外層,通過DNS域名的輪詢機制,實現使用者請求在Node這一層上的“負載均衡”;
- 訪問某個NodeIP:NodePort的請求,被轉發到Nginx ClusterIP: Port,並通過iptables nat的負載機制,分發到Nginx service的多個real endpoints上;
- 位於real endpoint上的Nginx程式處理使用者請求,並根據配置,將請求proxy_pass到後端服務的ClusterIP:Port上,並最終由k8s實現將請求均衡分發到後端服務的endpoint。
二、Nginx入口服務部署
部署前,我們先來給執行Nginx Pod的Node打label:
# kubectl label node/10.47.136.60 role=entry
node "10.47.136.60" labeled
# kubectl label node/10.47.136.60 role=entry
node "10.47.136.60" labeled
# kubectl get nodes --show-labels
NAME STATUS AGE LABELS
10.46.181.146 Ready 39d beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=10.46.181.146,role=entry,zone=ceph
10.47.136.60 Ready 39d beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=10.47.136.60,role=entry,zone=ceph
在Nginx配置熱載入方案一文中,我們提到一個nginx pod中包含三個Container:nginx、nginx-conf-generator和init container,Nginx service的yaml示例如下:
//nginx-kit.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-kit
spec:
replicas: 2
template:
metadata:
labels:
run: nginx-kit
annotations:
pod.beta.kubernetes.io/init-containers: '[
{
"name": "nginx-kit-init-container",
"image": "registry.cn-beijing.aliyuncs.com/xxxx/nginx-conf-generator",
"imagePullPolicy": "IfNotPresent",
"command": ["/root/conf-generator/nginx-conf-gen", "-mode", "gen-once"],
"volumeMounts": [
{
"name": "conf-volume",
"mountPath": "/etc/nginx/conf.d"
}
]
}
]'
spec:
containers:
- name: nginx-conf-generator
volumeMounts:
- mountPath: /etc/nginx/conf.d
name: conf-volume
image: registry.cn-beijing.aliyuncs.com/xxxx/nginx-conf-generator:latest
imagePullPolicy: IfNotPresent
- name: xxxx-nginx
volumeMounts:
- mountPath: /etc/nginx/conf.d
name: conf-volume
image: registry.cn-hangzhou.aliyuncs.com/xxxx/nginx:latest
imagePullPolicy: IfNotPresent
command: ["/home/auto-reload-nginx.sh"]
ports:
- containerPort: 80
volumes:
- name: conf-volume
emptyDir: {}
nodeSelector:
role: entry
---
apiVersion: v1
kind: Service
metadata:
name: nginx-kit
labels:
run: nginx-kit
spec:
type: NodePort
ports:
- port: 80
nodePort: 28888
protocol: TCP
selector:
run: nginx-kit
關於這個yaml,有幾點我們是必須要說說的:
1、關於init container
通過上述yaml檔案內容,我們可以看到init container和nginx-conf-generator container都是基於同一映象建立的,只是工作mode不同罷了。在deployment描述檔案中,init container的描述需要放在deployment.spec.template.metadata下面,而不是deployment的metadata下面。如果按照後者編寫,那麼init container將不會被建立和啟動,nginx container啟動後也就會提示:找不到”default.conf”。
另外,雖然源自同一個image,但init container啟動時卻提示在$PATH裡找不到名為”-mode”的可執行程式,顯然init container中的ENTRYPOINT並不起作用,nginx-conf-generator的Dockerfile節選如下:
//Dockerfile
From ubuntu:14.04
... ...
ENTRYPOINT ["/root/conf-generator/nginx-conf-gen"]
為此我們在init container的”command”命令引數中增加了可執行程式全路徑以供container執行:
"command" : ["/root/conf-generator/nginx-conf-gen", "-mode", "gen-once"],
最後,通過上面yaml檔案建立nginx-kit服務依舊要用kubectl apply,而不是kubectl create,否則init container不會被理會。
2、關於nginx conf模板
由於種種原因,當前我們是通過server host的location path來對映後端cluster中的不同Service的,nginx default.conf模板如下:
server {
listen 80;
#server_name opp.neusoft.com;
{{range .}}
location {{.Path}} {
proxy_pass http://{{.ClusterIP}}:{{.Port}}/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
{{end}}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
這裡要注意的是proxy_pass directive後面值的寫法,如果你選擇這樣寫:
proxy_pass http://{{.ClusterIP}}:{{.Port}};
那麼當訪問某個路徑時,比如:localhost/volume/api/v1/pools時,nginx後端的Service收到的url訪問路徑將是:/volume/api/v1/pools,volume這個location path並不能被去除,後端的Service在做路由匹配時基本都是會出錯的。fix的方法是賦予proxy_pass directive下面這樣的值:
proxy_pass http://{{.ClusterIP}}:{{.Port}}/;
沒錯,在最後加上一個”/”,這樣nginx所反向代理的Service將會收到/api/v1/pools這樣的訪問URl路徑。
© 2016~2018, Enweitech. 版權所有.
相關文章
- Kubernetes部署叢集Mysql服務MySql
- 13、nginx服務叢集搭建以及優化Nginx優化
- 基於Kubernetes叢集部署skyDNS服務DNS
- Terraform部署容器服務Swarm叢集及WordPress應用ORMSwarm
- 拆除kubeadm部署的Kubernetes 叢集
- 基於Ubuntu部署企業級kubernetes叢集---k8s叢集容部署UbuntuK8S
- Linux 部署 Nginx 服務LinuxNginx
- 如何發現 Kubernetes 中服務和工作負載的異常負載
- 使用Docker Swarm快速搭建與部署你的服務叢集DockerSwarm
- Kubernetes 部署 Nebula 圖資料庫叢集資料庫
- 基於containerd 部署 kubernetes 1.28叢集AI
- 實現Kubernetes跨叢集服務應用的高可用
- kubernetes入門 基礎叢集部署
- [雲原生微服務架構](十一) Kubernetes高可用叢集二進位制部署(Runtime Containerd)微服務架構AI
- 使用Rancher在Kubernetes上部署EMQ X叢集MQ
- socket服務叢集處理
- WEB叢集- 高可用服務Web
- 在kubernetes 叢集內訪問k8s API服務K8SAPI
- 叢集二nginxNginx
- SpringCloud微服務實戰——搭建企業級開發框架(三十五):SpringCloud + Docker + k8s實現微服務叢集打包部署-叢集環境部署SpringGCCloud微服務框架DockerK8S
- 為Kubernetes叢集部署本地映象倉庫
- Kubernetes實戰:高可用叢集的搭建和部署
- 利用 Kubeadm部署 Kubernetes 1.13.1 叢集實踐錄
- 容器化 | 在 Kubernetes 上部署 RadonDB MySQL 叢集MySql
- Kubernetes(k8s)部署redis-cluster叢集K8SRedis
- docker初體驗:docker部署nginx負載均衡叢集DockerNginx負載
- Spark叢集和任務執行Spark
- 分散式、微服務、叢集,個人理解分散式微服務
- 部署分片叢集
- 將微服務部署到 Azure Kubernetes 服務 (AKS) 實踐微服務
- nginx主主叢集Nginx
- 乾貨|Kubernetes叢集部署 Nginx-ingress ControllerNginxController
- 使用 Kubeadm+Containerd 部署一個 Kubernetes 叢集AI
- 實踐展示openEuler部署Kubernetes 1.29.4版本叢集
- docker初體驗:docker部署nginx服務DockerNginx
- Node.js + Nginx 部署 HTTPS 服務Node.jsNginxHTTP
- Redis服務之叢集節點管理Redis
- Docker中提交任務到Spark叢集DockerSpark