Kubernetes Nginx Ingress教程

【摘要】最近發現好多人問Ingress,同時一直也沒去用Nginx的Ingress,索性搗鼓一把,發現跟原來確實有了點變化,在這裏寫篇文章記錄一下 1、Ingress介紹 Kubernetes暴露服務的方式目前只有三種:LoadBalancer Service、NodePort Service、Ingress;前兩種估計都應該很熟悉,具體的能夠參考下 這篇文章;下面想寫介紹一下這個Ingre...

最近發現好多人問Ingress,同時一直也沒去用Nginx的Ingress,索性搗鼓一把,發現跟原來確實有了點變化,在這裏寫篇文章記錄一下javascript

1、Ingress介紹

Kubernetes暴露服務的方式目前只有三種:LoadBalancer Service、NodePort Service、Ingress;前兩種估計都應該很熟悉,具體的能夠參考下 這篇文章;下面想寫介紹一下這個Ingress。前端

1.1 Ingress是個什麼玩意

可能從大體印象上Ingress就是能利用Nginx、Haproxy啥的負載均衡器暴露集羣內服務的工具;那麼問題來了,集羣內服務想要暴露出去面臨着幾個問題:java

1.二、Pod漂移問題

衆所周知Kubernetes具備強大的副本控制能力,能保證在任意副本(Pod)掛掉時自動從其餘機器啓動一個新的,還能夠動態擴容等,總之一句話,這個Pod可能在任什麼時候刻出如今任何節點上,也可能在任什麼時候刻死在任何節點上;那麼天然隨着Pod的建立和銷燬,Pod IP確定會動態變化;那麼如何把這個動態的Pod IP暴露出去?這裏藉助於Kubernetes的Service機制,Service能夠以標籤的形式選定一組帶有指定標籤的Pod,並監控和自動負載他們的Pod IP,那麼咱們向外暴露只暴露Service IP就好了;這就是NodePort模式:即在每一個節點上開啓一個端口,而後轉發到內部Pod IP上,以下圖所示:node

Kubernetes Nginx Ingress教程1

1.三、端口管理問題

採用NodePort方式暴露服務面臨着一個坑爹的問題是,服務一旦多起來,NodePort在每一個節點上開啓的端口會及其龐大,並且難以維護;這時候引出的思考問題是"能不能使用Nginx啥的只監聽一個端口,好比80,而後按照域名向後轉發?"這思路很好,簡單的實現就是使用DaemonSet在每一個node上監聽80,而後寫好規則,由於Nginx外面綁定了宿主機80端口(就像NodePort),自己又在集羣內,那麼向後直接轉發到相應Service IP就好了,以下圖所示:nginx

Kubernetes Nginx Ingress教程2

1.四、域名分配及動態更新問題

從上面的思路,採用Nginx彷佛已經解決了問題,可是其實這裏面有一個很大缺陷:每次有新服務加入怎麼改Nginx配置?總不能手動改或者來個Rolling Update前端Nginx Pod吧?這時候"偉大而又正直勇敢的"Ingress"登場,若是不算上面的Nginx,Ingress只有兩大組件:Ingress Controller和Ingressgit

Ingress這個玩意,簡單的理解就是你原來要改Nginx配置,而後配置各類域名對應哪一個Service,如今把這個動做抽象出來,變成一個Ingress對象,你能夠用yml建立,每次不要去改Nginx了,直接改yml而後建立/更新就好了;那麼問題來了「Nginx咋整?」vim

Ingress Controller這東西就是解決"Nginx咋整"的;Ingress Controller經過與Kubernetes API交互,動態的去感知集羣中Ingress規則變化,而後讀取他,按照他本身模板生成一段Nginx配置,再寫到Nginx Pod裏,最後reload一下,工做流程以下圖後端

Kubernetes Nginx Ingress教程3

固然在實際應用中,最新版本Kubernetes已經將Nginx與Ingress Controller合併爲一個組件,因此Nginx無需單獨部署,只須要部署Ingress Controller便可api

2、懟一個Nginx Ingress

上面囉嗦了那麼多,只是爲了講明白Ingress的各類理論概念,下面實際部署很簡單負載均衡

2.一、部署默認後端

咱們知道前端的Nginx最終要負載到後端service上,那麼若是訪問不存在的域名咋整?官方給出的建議是部署一個默認後端,對於未知請求所有負載到這個默認後端上;這個後端啥也不幹,就是返回404,部署以下:

-> ~ kubectl create -f default-backend.yaml
deployment "default-http-backend" created
service "default-http-backend" created

這個default-backend.yaml文件能夠在 官方 Ingress 倉庫 找到,倉庫位置以下:

Kubernetes Nginx Ingress教程4

2.二、部署Ingress Controller

部署完了後端就得把最重要的組件Nginx+Ingress Controller(官方統一稱爲Ingress Controller)部署上

-> ~ kubectl create -f nginx-ingress-controller.yaml
daemonset "nginx-ingress-1b" created

注意:官方的 Ingress Controller 有個坑,至少我看了 DaemonSet 方式部署的有這個問題:沒有綁定到宿主機 80 端口,也就是說前端 Nginx 沒有監聽宿主機 80 端口(這還玩個卵啊);因此須要把配置搞下來本身加一下 hostNetwork,截圖以下

Kubernetes Nginx Ingress教程5

一樣配置文件本身找一下,地址 點這裏,倉庫截圖以下

Kubernetes Nginx Ingress教程6

固然它支持以 deamonset 的方式部署,這裏用的就是(我的喜歡而已),因此你發現我上面截圖是 deployment,可是連接給的倒是 daemonset,由於我截圖截錯了…..

2.三、部署Ingress

這個可就厲害了,這個部署完就能裝逼了

回到正題,從上面能夠知道 Ingress 就是個規則,指定哪一個域名轉發到哪一個 Service,因此說首先咱們得有個 Service,固然 Service 去哪找這裏就無論了;這裏默認爲已經有了兩個可用的 Service,如下以 Dashboard 和 kibana 爲例

先寫一個 Ingress 文件,語法格式啥的請參考 官方文檔,因爲個人 Dashboard 和 Kibana 都在 kube-system 這個命名空間,因此要指定 namespace,寫以前 Service 分佈以下

Kubernetes Nginx Ingress教程7

vim dashboard-kibana-ingress.yml

apiVersion: extensions/v1beta1
kind: Ingress
metadata: name: dashboard-kibana-ingress namespace: kube-system
spec: rules: - host: dashboard.mritd.me http: paths: - backend: serviceName: kubernetes-dashboard servicePort: 80 - host: kibana.mritd.me http: paths: - backend serviceName: kibana-logging servicePort: 5601

裝逼成功截圖以下

Kubernetes Nginx Ingress教程8

Kubernetes Nginx Ingress教程9

3、部署 Ingress TLS

上面已經搞定了 Ingress,下面就順便把 TLS 懟上;官方給出的樣例很簡單,大體步驟就兩步:建立一個含有證書的 secret、在 Ingress 開啓證書;可是我不得不噴一下,文檔就提那麼一嘴,大坑一堆,好比多域名配置,還有下面這文檔特麼的是逗我玩呢?

Kubernetes Nginx Ingress教程10

3.一、建立證書

首先第一步固然要有個證書,因爲我這個 Ingress 有兩個服務域名,因此證書要支持兩個域名;生成證書命令以下:

# 生成 CA 自簽證書
mkdir cert && cd cert
openssl genrsa -out ca-key.pem 2048
openssl req -x509 -new -nodes -key ca-key.pem -days 10000 -out ca.pem -subj "/CN=kube-ca"

# 編輯 openssl 配置
cp /etc/pki/tls/openssl.cnf .
vim openssl.cnf

# 主要修改以下
[req]
req_extensions = v3_req # 這行默認註釋關着的 把註釋刪掉
# 下面配置是新增的
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = dashboard.mritd.me
DNS.2 = kibana.mritd.me

# 生成證書
openssl genrsa -out ingress-key.pem 2048
openssl req -new -key ingress-key.pem -out ingress.csr -subj "/CN=kube-ingress" -config openssl.cnf
openssl x509 -req -in ingress.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out ingress.pem -days 365 -extensions v3_req -extfile openssl.cnf

3.二、建立 secret

建立好證書之後,須要將證書內容放到 secret 中,secret 中所有內容須要 base64 編碼,而後注意去掉換行符(變成一行);如下是個人 secret 樣例(上一步中 ingress.pem 是證書,ingress-key.pem 是證書的 key)

vim ingress-secret.yml

apiVersion: v1
data:
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM5akNDQWQ2Z0F3SUJBZ0lKQU5TR2dNNnYvSVd5TUEwR0NTcUdTSWIzRFFFQkJRVUFNQkl4RURBT0JnTlYKQkFNTUIydDFZbVV0WTJFd0hoY05NVGN3TXpBME1USTBPRFF5V2hjTk1UZ3dNekEwTVRJME9EUXlXakFYTVJVdwpFd1lEVlFRRERBeHJkV0psTFdsdVozSmxjM013Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUUM2dkNZRFhGSFpQOHI5Zk5jZXlkV015VVlELzAwQ2xnS0M2WjNpYWZ0QlRDK005TmcrQzloUjhJUE4KWW00cjZOMkw1MmNkcmZvQnBHZXovQVRIT0NJYUhJdlp1K1ZaTzNMZjcxZEVLR09nV21LMTliSVAzaGpSeDZhWQpIeGhEVWNab3ZzYWY1UWJHRnUydEF4L2doMTFMdXpTZWJkT0Y1dUMrWHBhTGVzWWdQUjhFS0cxS0VoRXBLMDFGCmc4MjhUU1g2TXVnVVZmWHZ1OUJRUXExVWw0Q2VMOXhQdVB5T3lMSktzbzNGOEFNUHFlaS9USWpsQVFSdmRLeFYKVUMzMnBtTHRlUFVBb2thNDRPdElmR3BIOTZybmFsMW0rMXp6YkdTemRFSEFaL2k1ZEZDNXJOaUthRmJnL2NBRwppalhlQ01xeGpzT3JLMEM4MDg4a0tjenJZK0JmQWdNQkFBR2pTakJJTUM0R0ExVWRFUVFuTUNXQ0VtUmhjMmhpCmIyRnlaQzV0Y21sMFpDNXRaWUlQYTJsaVlXNWhMbTF5YVhSa0xtMWxNQWtHQTFVZEV3UUNNQUF3Q3dZRFZSMFAKQkFRREFnWGdNQTBHQ1NxR1NJYjNEUUVCQlFVQUE0SUJBUUNFN1ByRzh6MytyaGJESC8yNGJOeW5OUUNyYVM4NwphODJUUDNxMmsxUUJ1T0doS1pwR1N3SVRhWjNUY0pKMkQ2ZlRxbWJDUzlVeDF2ckYxMWhGTWg4MU9GMkF2MU4vCm5hSU12YlY5cVhYNG16eGNROHNjakVHZ285bnlDSVpuTFM5K2NXejhrOWQ1UHVaejE1TXg4T3g3OWJWVFpkZ0sKaEhCMGJ5UGgvdG9hMkNidnBmWUR4djRBdHlrSVRhSlFzekhnWHZnNXdwSjlySzlxZHd1RHA5T3JTNk03dmNOaQpseWxDTk52T3dNQ0h3emlyc01nQ1FRcVRVamtuNllLWmVsZVY0Mk1yazREVTlVWFFjZ2dEb1FKZEM0aWNwN0sxCkRPTDJURjFVUGN0ODFpNWt4NGYwcUw1aE1sNGhtK1BZRyt2MGIrMjZjOVlud3ROd24xdmMyZVZHCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
  tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBdXJ3bUExeFIyVC9LL1h6WEhzblZqTWxHQS85TkFwWUNndW1kNG1uN1FVd3ZqUFRZClBndllVZkNEeldKdUsramRpK2RuSGEzNkFhUm5zL3dFeHpnaUdoeUwyYnZsV1R0eTMrOVhSQ2hqb0ZwaXRmV3kKRDk0WTBjZW1tQjhZUTFIR2FMN0duK1VHeGhidHJRTWY0SWRkUzdzMG5tM1RoZWJndmw2V2kzckdJRDBmQkNodApTaElSS1N0TlJZUE52RTBsK2pMb0ZGWDE3N3ZRVUVLdFZKZUFuaS9jVDdqOGpzaXlTcktOeGZBREQ2bm92MHlJCjVRRUViM1NzVlZBdDlxWmk3WGoxQUtKR3VPRHJTSHhxUi9lcTUycGRadnRjODJ4a3MzUkJ3R2Y0dVhSUXVhelkKaW1oVzRQM0FCb28xM2dqS3NZN0RxeXRBdk5QUEpDbk02MlBnWHdJREFRQUJBb0lCQUJtRmIzaVVISWVocFYraAp1VkQyNnQzVUFHSzVlTS82cXBzenpLVk9NTTNLMk5EZUFkUHhFSDZhYlprYmM4MUNoVTBDc21BbkQvMDdlQVRzClU4YmFrQ2FiY2kydTlYaU5uSFNvcEhlblFYNS8rKys4aGJxUGN6cndtMzg4K0xieXJUaFJvcG5sMWxncWVBOW0KVnV2NzlDOU9oYkdGZHh4YzRxaUNDdmRETDJMbVc2bWhpcFRKQnF3bUZsNUhqeVphdGcyMVJ4WUtKZ003S1p6TAplYWU0bTJDR3R0bmNyUktodklaQWxKVmpyRWoxbmVNa3RHODFTT3QyN0FjeDRlSnozbmcwbjlYSmdMMHcwU05ZCmlwd3I5Uk5PaDkxSGFsQ3JlWVB3bDRwajIva0JIdnozMk9Qb2FOSDRQa2JaeTEzcks1bnFrMHBXdUthOEcyY00KLzY4cnQrRUNnWUVBN1NEeHRzRFFBK2JESGdUbi9iOGJZQ3VhQ2N4TDlObHIxd2tuTG56VVRzRnNkTDByUm1uZAp5bWQ4aU95ME04aUVBL0xKb3dPUGRRY240WFdWdS9XbWV5MzFVR2NIeHYvWlVSUlJuNzgvNmdjZUJSNzZJL2FzClIrNVQ1TEMyRmducVd2MzMvdG0rS0gwc0J4dEM3U2tSK3Y2UndVQk1jYnM3c0dUQlR4NVV2TkVDZ1lFQXlaaUcKbDBKY0dzWHhqd1JPQ0FLZytEMlJWQ3RBVmRHbjVMTmVwZUQ4bFNZZ3krZGxQaCt4VnRiY2JCV0E3WWJ4a1BwSAorZHg2Z0p3UWp1aGN3U25uOU9TcXRrZW04ZmhEZUZ2MkNDbXl4ZlMrc1VtMkxqVzM1NE1EK0FjcWtwc0xMTC9GCkIvK1JmcmhqZW5lRi9BaERLalowczJTNW9BR0xRVFk4aXBtM1ZpOENnWUJrZGVHUnNFd3dhdkpjNUcwNHBsODkKdGhzemJYYjhpNlJSWE5KWnNvN3JzcXgxSkxPUnlFWXJldjVhc0JXRUhyNDNRZ1BFNlR3OHMwUmxFMERWZWJRSApXYWdsWVJEOWNPVXJvWFVYUFpvaFZ0U1VETlNpcWQzQk42b1pKL2hzaTlUYXFlQUgrMDNCcjQ0WWtLY2cvSlplCmhMMVJaeUU3eWJ2MjlpaWprVkVMRVFLQmdRQ2ZQRUVqZlNFdmJLYnZKcUZVSm05clpZWkRpNTVYcXpFSXJyM1cKSEs2bVNPV2k2ZlhJYWxRem1hZW1JQjRrZ0hDUzZYNnMyQUJUVWZLcVR0UGxKK3EyUDJDd2RreGgySTNDcGpEaQpKYjIyS3luczg2SlpRY2t2cndjVmhPT1Z4YTIvL1FIdTNXblpSR0FmUGdXeEcvMmhmRDRWN1R2S0xTNEhwb1dQCm5QZDV0UUtCZ0QvNHZENmsyOGxaNDNmUWpPalhkV0ZTNzdyVFZwcXBXMlFoTDdHY0FuSXk5SDEvUWRaOXYxdVEKNFBSanJseEowdzhUYndCeEp3QUtnSzZmRDBXWmZzTlRLSG01V29kZUNPWi85WW13cmpPSkxEaUU3eFFNWFBzNQorMnpVeUFWVjlCaDI4cThSdnMweHplclQ1clRNQ1NGK0Q5NHVJUmkvL3ZUMGt4d05XdFZxCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
kind: Secret
metadata:
  name: ingress-secret
  namespace: kube-system
type: Opaque

建立完成後 create 一下就可

~ kubectl create -f ingress-secret.yml
secret "ingress-secret" created

其實這個配置好比證書轉碼啥的不必手動去作,能夠直接使用下面的命令建立,這裏寫這麼多隻是爲了把步驟寫清晰

kubectl create secret tls ingress-secret --key cert/ingress-key.pem --cert cert/ingress.pem

3.三、從新部署 Ingress

生成完成後須要在 Ingress 中開啓 TLS,Ingress 修改後以下

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: dashboard-kibana-ingress
  namespace: kube-system
spec:
  tls:
  - hosts: - dashboard.mritd.me - kibana.mritd.me secretName: ingress-secret
  rules:
  - host: dashboard.mritd.me http: paths: - backend: serviceName: kubernetes-dashboard servicePort: 80
  - host: kibana.mritd.me http: paths: - backend: serviceName: kibana-logging servicePort: 5601

注意:一個 Ingress 只能使用一個 secret(secretName 段只能有一個),也就是說只能用一個證書,更直白的說就是若是你在一個 Ingress 中配置了多個域名,那麼使用 TLS 的話必須保證證書支持該 Ingress 下全部域名;而且這個 secretName 必定要放在上面域名列表最後位置,不然會報錯 did not find expected key 沒法建立;同時上面的 hosts 段下域名必須跟下面的 rules 中徹底匹配

更須要注意一點:之因此這裏單獨開一段就是由於有大坑;Kubernetes Ingress 默認狀況下,當你不配置證書時,會默認給你一個 TLS 證書的,也就是說你 Ingress 中配置錯了,好比寫了2個 secretName、或者 hosts 段中缺了某個域名,那麼對於寫了多個 secretName 的狀況,全部域名全會走默認證書;對於 hosts 缺了某個域名的狀況,缺失的域名將會走默認證書,部署時必定要驗證一下證書,不能 「有了就行」;更新 Ingress 證書可能須要等一段時間纔會生效

最後從新部署一下便可

~ kubectl delete -f dashboard-kibana-ingress.yml
ingress "dashboard-kibana-ingress" deleted
➜  ~ kubectl create -f dashboard-kibana-ingress.yml
ingress "dashboard-kibana-ingress" created

注意:部署 TLS 後 80 端口會自動重定向到 443,最終訪問截圖以下

Kubernetes Nginx Ingress教程11

Kubernetes Nginx Ingress教程12

歷時 5 個小時鼓搗,到此結束

相關文章
相關標籤/搜索