先熟悉k8s
這一節(jié)我們先熟悉一下 k8s,并且利用這個過程了解為什么需要 traefik。如果你已經(jīng)做過調(diào)研,可以安全的跳過這一節(jié)。
這一節(jié)的任務(wù)是部署一個 nginx 。我們需要編寫配置文件,應(yīng)用到 k8s 中。之后 k8s 會根據(jù)配置文件中的設(shè)置自動下載 nignx 的鏡像并且運行。
首先第一個文件是 nginx-deployment.yml ,內(nèi)容如下:
apiVersion: apps/v1 # 1.9.0 之前使用 apps/v1beta2
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 1 # 告訴k8s只運行一個實例
template: # 這下面是pod
metadata:
labels:
app: nginx # 記住這里
spec:
containers:
- name: nginx
image: nginx:1.7.9 # nginx鏡像
ports:
- containerPort: 80
這個配置文件部署了兩個東西, pod 和 deployment。它們的關(guān)系如下圖所示。
[圖片上傳失敗...(image-2561bb-1573183728438)]
pod 是 k8s 中調(diào)度的最小單位, deployment 是一個 controller 我們下面都稱作控制器,它的目的就是按照配置文件所描述的那樣控制 pod 的狀態(tài)。如果 pod 掛了, deployment 負責(zé)重啟 pod 。而如果 replicas 設(shè)置為2,就會變成下面這樣:
[圖片上傳失敗...(image-70b936-1573183728438)]
編寫好以后,我們直接應(yīng)用

然后我們來看看 pod 的狀態(tài)。

看到已經(jīng) running 了,并且 ready 也是 1/1 了。
但是這個時候,我們只能在 k8s 內(nèi)部訪問這個 pod ,而不能從外部訪問。
要想從外部訪問,我們需要再寫一個配置文件 nginx-service.yml ??创a:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app: nginx # 這里對應(yīng)上面的 *記住這里*
ports:
- protocol: TCP
port: 80 # k8s中服務(wù)的訪問端口,用于k8s內(nèi)部訪問
nodePort: 30000 # 映射到物理服務(wù)器上的端口,用于k8s外部訪問,記住這個端口號
targetPort: 80 # pod的端口
service 也是一個 controller,它的作用是暴露 pod 的服務(wù)。暴露哪個 pod 的服務(wù)呢?其實就是 selector 選中的 pod 。我們也來應(yīng)用一下:

接著我們用命令看看這個 service :

kubernetes 這個服務(wù)本來就有,我們先不管它。我們看到我們的 my-service 已經(jīng)存在了。接著我們來訪問訪問。



你猜的沒錯,我換 ip 了,不要在意這些細節(jié)。我們能看到的是,我們部署了一個 nginx ,而三臺服務(wù)器相同的端口下面都能訪問到。一般情況下,在線上只需要暴露一個服務(wù)器到公網(wǎng)即可。
配置文件可以合并,如果你愿意,可以把上面的兩個配置文件的內(nèi)容復(fù)制到一個文件中,用---(三個短橫線)分割。
如果你深入研究 k8s 你會發(fā)現(xiàn)你找不到一個方法來做域名路由,實際上 k8s 也沒有提供這樣一個方法。也就是說,當(dāng)你需要部署兩個網(wǎng)站的時候,你只能通過端口號來區(qū)分它們。要想解決這個問題,我們就需要 traefik 了(終于繞回來了~)。
treafik
與 traefik 有一樣作用的還有 nginx-ingress ,我們這里只研究 traefik 。
不過首先,我們需要修改一下
k8s的配置。上面nginx的端口我設(shè)置的30000,其實我是想設(shè)置8080的,但是失敗了。
失敗
上面說有效的端口是30000-32767,這可不是我們想要了。所以,我們需要修改api-server這個pod的配置文件來讓k8s接管幾乎所有的端口。
api-server這個pod是k8s自身的組件,它的配置文件是/etc/kubernetes/manifests/kube-apiserver.yaml。我們在啟動參數(shù)中加入一項。
修改配置
由于這個系統(tǒng)組件的配置文件是常駐的,所有我們只需要保存,被修改的pod就會自動重啟。
在api-server組件重啟期間你是無法使用k8s命令的,這也說明其實真正執(zhí)行我們命令的就是api-server組件。
觀察
就在前段時間 traefik 發(fā)布了2.0版本,我們也直接來嘗嘗鮮。文檔里其實已經(jīng)講的很詳細了,上面說我們需要寫四個配置文件。我們照著這個上面來,先應(yīng)用第一個配置。就是文檔里面的 IngressRoute Definition 節(jié)的第一個代碼塊。

第二個, traefik 的 service 配置(文檔里面 service 節(jié)的第一個代碼塊),不過這里,我們需要改一改。
apiVersion: v1
kind: Service
metadata:
name: traefik
spec:
type: NodePort
ports:
- protocol: TCP
name: web
port: 80
nodePort: 80
- protocol: TCP
name: admin
port: 8080
nodePort: 8080
- protocol: TCP
name: websecure
port: 443
nodePort: 443
selector:
app: traefik
我們應(yīng)用它:

最后是 deployment (文檔里面 deployments 節(jié)的第一個代碼塊),也要改一改:
apiVersion: v1
kind: ServiceAccount
metadata:
namespace: default
name: traefik-ingress-controller
---
kind: Deployment
apiVersion: apps/v1
metadata:
namespace: default
name: traefik
labels:
app: traefik
spec:
replicas: 1
selector:
matchLabels:
app: traefik
template:
metadata:
labels:
app: traefik
spec:
serviceAccountName: traefik-ingress-controller
containers:
- name: traefik
image: traefik:v2.0
args:
- --api.insecure
- --accesslog
- --entrypoints.web.Address=:80 # http訪問80
- --entrypoints.websecure.Address=:443 # https訪問443
- --providers.kubernetescrd # 這個定式,固定寫就好
- --certificatesresolvers.default.acme.tlschallenge # 這個是let's Encrypt配置,跟下面兩個固定寫,可以自動幫你申請證書,你沒有看錯,是自動的。
- --certificatesresolvers.default.acme.email=foo@you.com # 這地方填你自己郵箱地址,這樣你能收到let's Encrypt對你這個域名的通知。
- --certificatesresolvers.default.acme.storage=acme.json # 定式
ports:
- name: web # 端口可以命名,這樣service就可以直接使用端口名代替端口,往上看service的配置文件。
containerPort: 8000
- name: websecure
containerPort: 4443
- name: admin
containerPort: 8080
好,我們應(yīng)用它:

接著我們查看一下 pod :

可以看到 traefik 的 pod 已經(jīng) running 了,怎么確定它已經(jīng)部署成功了呢?我們試試訪問 80 和 8080 ( 443 我就不訪問,因為是在本地虛擬機上面,公網(wǎng)到不到,所以 let's Encrypt 無法自動設(shè)置 https )。


上面 404 是因為我們還沒有部署任何服務(wù), traefik 找不到要代理的東西,無奈的打出了 404 。
接下來我們看看怎么使用它。老規(guī)矩,上 nginx 。
apiVersion: apps/v1 # 1.9.0 之前使用 apps/v1beta2
kind: Deployment
metadata:
name: new-nginx-deployment
spec:
selector:
matchLabels:
app: new-nginx
replicas: 1 # 告訴k8s只運行一個實例
template: # 這下面是pod
metadata:
labels:
app: new-nginx # 記住這里
spec:
containers:
- name: nginx
image: nginx:1.7.9 # nginx鏡像
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: new-my-service
spec:
# type: NodePort traefik會自己將服務(wù)暴露出來,所以不用我們自己暴露了
selector:
app: new-nginx # 這里對應(yīng)上面的 *記住這里*
ports:
- protocol: TCP
port: 80 # k8s中服務(wù)的訪問端口,用于k8s內(nèi)部訪問
# nodePort: 30000 # traefik會自己將服務(wù)暴露出來,所以不用我們自己暴露了
targetPort: 80 # pod的端口
這個配置文件跟上面的沒有太大區(qū)別,就是沒有暴露服務(wù),和改了名字。并且將 service 和 deployment 合到了一起。應(yīng)用它:

關(guān)鍵的來了,為了讓 traefik 暴露我們的服務(wù),我們還需要一個配置:
# 這個是http
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: simpleingressroute
namespace: default
spec:
entryPoints:
- web # 也就是traefik的80端口
routes:
- match: Host(`your.domain.com`) # 里面填你的域名,match還有其他函數(shù)(我們姑且就叫函數(shù)吧),可以參考文檔
kind: Rule
services:
- name: new-my-service # 填服務(wù)的名字
port: 80
---
# 這個是https
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroutetls
namespace: default
spec:
entryPoints:
- websecure # 也就是traefik的443端口
routes:
- match: Host(`your.domain.com`) # 里面填你的域名
kind: Rule
services:
- name: new-my-service # 填服務(wù)的名字
port: 80
tls:
certResolver: default
盤它~:

我們再來訪問(訪問之前記得添加 host ):


還是看一看 https 會是什么效果:

最后我們再來看看 traefik 管理端的情況:


對了, traefik 2.0 加入的新特性之一就是支持 tcp 連接了,因為我了解到有一些變態(tài)大佬已經(jīng)開始用二進制(比如 protobuf)來做前后端數(shù)據(jù)交互了。



