kubernetes之部署traefik-ingress分為http和https


1 理解Ingress

簡單的說,ingress就是從kubernetes集群外訪問集群的入口,將用戶的URL請求轉發到不同的service上。Ingress相當於nginx、apache等負載均衡方向代理服務器,其中還包括規則定義,即URL的路由信息,路由信息得的刷新由 Ingress controller來提供。

2 理解Ingress Controller

Ingress Controller 實質上可以理解為是個監視器,Ingress Controller 通過不斷地跟 kubernetes API 打交道,實時的感知后端 service、pod 等變化,比如新增和減少 pod,service 增加與減少等;當得到這些變化信息后,Ingress Controller 再結合下文的 Ingress 生成配置,然后更新反向代理負載均衡器,並刷新其配置,達到服務發現的作用。

3 RBAC

在開始之前,需要先了解一下什么是RBAC。RBAC(基於角色的訪問控制)使用 rbac.authorization.k8s.io API 組來實現權限控制,RBAC 允許管理員通過 Kubernetes API 動態的配置權限策略。在 1.6 版本中 RBAC 還處於 Beat 階段,如果想要開啟 RBAC 授權模式需要在 apiserver 組件中指定 --authorization-mode=RBAC 選項。

在 RBAC API 的四個重要概念: 

Role:是一系列的權限的集合,例如一個角色可以包含讀取 Pod 的權限和列出 Pod 的權限 
ClusterRole: 跟 Role 類似,但是可以在集群中到處使用( Role 是 namespace 一級的) 
RoloBinding:把角色映射到用戶,從而讓這些用戶繼承角色在 namespace 中的權限。 
ClusterRoleBinding: 讓用戶繼承 ClusterRole 在整個集群中的權限。

4 部署traefik

首先部署一個 ingress controller 類型的 pod,pod中運行的容器是traefik,然后選擇是通過基於不同的域名或者不同的 URL,關聯到不同的 service。而后通過 ingress 來監控 service 的變化,最終形成相應的配置文件。
4.1 創建ingress-rbac.yaml
將用於service account驗證。部署之前先創建 clusterRoleBinding,它的作用是將下面列出的權限授予給 traefik-ingress-controller 這個 ServiceAccount,然后 pod 就由這個用戶啟動。這樣一來,pod 就擁有這些權限了。
$ cat ingress-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ingress
  namespace: kube-system

---

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: ingress
subjects:
  - kind: ServiceAccount
    name: ingress
    namespace: kube-system
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

4.2  創建DaemonSet

traefik 可以部署為 Deployment 和 DaemonSet 兩種模式,如果使用官方提供的 deployment 的安裝方式,traefik pod 的 80/443/8080 端口會通過 NodePort 的方式暴露出來,也就是說你無法通過節點的 ip + 80 端口進行訪問,因此你前面還得給它加上一個負載均衡器。
而官方的 DaemonSet 就不存在這樣的問題了,它使用的是 NET_BIND_SERVICE 這樣一個 capabilities,意思是可以直接使用宿主機網絡名稱空間的端口。使用它之后,你在宿主機上看不到它監聽了 80 端口,但是你卻可以直接訪問,而不是 Deployment 這樣的 NodePort 方式。但是 DaemonSet 的缺點也很明顯,你的 node 節點數量越多,就越消耗資源。
有沒有兩全其美的方法呢?那肯定是有的,無論你使用 Deployment 還是 DaemonSet,只要都使用 NET_BIND_SERVICE,然后定義好節點的親和性或者污點就能讓 pod 只運行在特定的節點上,然后域名解析指向這些節點就行。當然前提是這些節點的 80/443 都沒有被占用。
我們使用DaemonSet類型來部署Traefik,並使用nodeSelector來限定Traefik所部署的主機。

4.2.1 創建節點標簽

選擇節點來調度traefik-ingress-lb運行在它上面
kubectl label nodes 172.19.8.114 edgenode=true
kubectl label nodes 172.19.8.115 edgenode=true

4.2.2 部署traefik-ingress-controller.yml

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: traefik-ingress-lb
  namespace: kube-system
  labels:
    k8s-app: traefik-ingress-lb
spec:
  template:
    metadata:
      labels:
        k8s-app: traefik-ingress-lb
        name: traefik-ingress-lb
    spec:
      terminationGracePeriodSeconds: 60
      hostNetwork: true
      restartPolicy: Always
      serviceAccountName: ingress
      containers:
      - image: traefik
        name: traefik-ingress-lb
        resources:
          limits:
            cpu: 200m
            memory: 30Mi
          requests:
            cpu: 100m
            memory: 20Mi
        ports:
        - name: http
          containerPort: 80
          hostPort: 80
        - name: admin
          containerPort: 8080
          hostPort: 8080
        args:
        - --web
        - --web.address=:8080
        - --kubernetes
        - --insecureskipverify
      nodeSelector:
        edgenode: "true"

4.3 配置traefik UI

使用下面的yaml配置來創建Traefik的Web UI。
$ cat ui.yaml
apiVersion: v1
kind: Service
metadata:
  name: traefik-web-ui
  namespace: kube-system
spec:
  selector:
    k8s-app: traefik-ingress-lb
  ports:
  - name: web
    port: 80
    targetPort: 8580
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: traefik-web-ui
  namespace: kube-system
spec:
  rules:
  - host: traefikui.test.com
    http:
      paths:
      - path: /
        backend:
          serviceName: traefik-web-ui
          servicePort: web

配置完成后就可以啟動treafik ui ingress了。

這其中的backend中要配置default namespace中啟動的service名字,如果你沒有配置namespace名字,默認使用default namespace,如果你在其他namespace中創建服務想要暴露到kubernetes集群外部,可以創建新的ingress.yaml文件,同時在文件中指定該namespace,其他配置與上面的文件格式相同。。path 就是URL地址后的路徑,如traefik.frontend.io/path,service將會接受path這個路徑,host最好使用service-name.filed1.filed2.domain-name這種類似主機名稱的命名方式,方便區分服務。
根據你自己環境中部署的service的名字和端口自行修改,有新service增加時,修改該文件后可以使用kubectl replace -f ui.yaml來更新。

4.3.1 訪問測試

修改本地hosts    172.19.8.115   traefikui.test.com

5 配置traefik支持https

5.1 https介紹

設置https有2種方式
1、 client與traefik間采用https加密通信,但traefik與svc間則是明文的http通信
client --- (via https) ---> traefik ---- (via http) ---->  services

2、 client與traefik間采用https加密通信,但traefik與svc也是采用https通信

client --- (via https) ---> traefik ---- (via https) ---->  services

5.2 配置證書

證書本地存放路徑 /etc/kubernetes/ssl/
# mkdir /etc/kubernetes/ssl/
# cd /etc/kubernetes/ssl/
# 將證書存放在此目錄
# ls 
pt1.20201216.key  pt1.20201216.pem

5.3  創建secret,保存https證書,注意操作目錄,如果不是在此目錄下操作,須指定絕對路徑,同時配置traefik多域名證書形式,traefik能夠自動識別證書

[root@node-01 ssl]# kubectl create secret generic traefik-cert --from-file=/etc/kubernetes/ssl/pt1.20201216.key --from-file=/etc/kubernetes/ssl/pt1.20201216.pem
--from-file=/etc/kubernetes/ssl/pt2.20201216.key --from-file=/etc/kubernetes/ssl/pt2.20201216.pem 
-n kube-system

5.4  創建configmap,保存traefik配置

說明:此處兩種配置方式,1.所有http請求全部rewrite為https。2.區分http和https兩種請求。此處使用第二種

# 1.所有http請求全部rewrite為https
[root@node-01 traefik]# cat traefik.toml
defaultEntryPoints = ["http","https"]
[entryPoints]
  [entryPoints.http]
  address = ":80"
    [entryPoints.http.redirect]
    entryPoint = "https"
  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]
      [[entryPoints.https.tls.certificates]]
      certFile = "/etc/kubernetes/ssl/pt1.20201216.pem"
      keyFile = "/etc/kubernetes/ssl/pt1.20201216.key"
      [[entryPoints.https.tls.certificates]]
      certFile = "/etc/kubernetes/ssl/pt2.20201216.pem" keyFile = "/etc/kubernetes/ssl/pt2.20201216.key"
 
# 2.區分http和https兩種請求
[root@node-01 traefik]# cat traefik.toml
defaultEntryPoints = ["http","https"]
[entryPoints]
  [entryPoints.http]
  address = ":80"
    entryPoint = "https"
  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]
      [[entryPoints.https.tls.certificates]]
      certFile = "/etc/kubernetes/ssl/pt1.20201216.pem"
      keyFile = "/etc/kubernetes/ssl/pt1.20201216.key"
      [[entryPoints.https.tls.certificates]]
      certFile = "/etc/kubernetes/ssl/pt2.20201216.pem" keyFile = "/etc/kubernetes/ssl/pt2.20201216.key"
 

注意:部署traefik.toml的節點,需要根據traefik.toml中指明的位置存放證書文件
[root@node-01 traefik]# kubectl create configmap traefik-conf --from-file=traefik.toml -n kube-system
  [root@node-01 traefik]# kubectl get cm -n kube-system
  NAME                                 DATA   AGE
  traefik-conf                         1      13s

查看創建的configmap

[root@node-01 traefik]# kubectl get configmap traefik-conf -o yaml -n kube-system
apiVersion: v1
data:
  traefik.toml: |
    defaultEntryPoints = ["http","https"]
    [entryPoints]
      [entryPoints.http]
      address = ":80"
        entryPoint = "https"
      [entryPoints.https]
      address = ":443"
        [entryPoints.https.tls]
          [[entryPoints.https.tls.certificates]]
          certFile = "/etc/kubernetes/ssl/pt1.20201216.pem"
          keyFile = "/etc/kubernetes/ssl/pt1.20201216.key"
          [[entryPoints.https.tls.certificates]]
          certFile = "/etc/kubernetes/ssl/pt2.20201216.pem" keyFile = "/etc/kubernetes/ssl/pt2.20201216.key"

kind: ConfigMap metadata: creationTimestamp: "2019-05-07T11:31:07Z" name: traefik-conf namespace: kube-system resourceVersion: "222740" selfLink: /api/v1/namespaces/kube-system/configmaps/traefik-conf uid: 9b315499-70bb-11e9-9a10-fa0caed1a100

5.5  部署traefik,這里主要是要關聯創建的secret和configmap,並掛載到pod中的目錄。

5.5.1  為主機打標簽,確定traefik部署在哪些node上面

kubectl label nodes 172.19.8.114 edgenode=true
kubectl label nodes 172.19.8.115 edgenode=true

5.5.2  由於k8s啟用了rbac,因此需要創建權限

[root@node-01 traefik]# cat ingress-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: traefik-ingress-controller
  namespace: kube-system

---

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: traefik-ingress-controller
subjects:
  - kind: ServiceAccount
    name: traefik-ingress-controller
    namespace: kube-system
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

我們使用DaemonSet類型來部署Traefik,並使用nodeSelector來限定Traefik所部署的主機。

[root@node-01 traefik]# cat traefik-deployment.yaml
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
  name: traefik-ingress-controller
  namespace: kube-system
  labels:
    k8s-app: traefik-ingress-lb
spec:
  selector:
    matchLabels:
      k8s-app: traefik-ingress-lb
  template:
    metadata:
      labels:
        k8s-app: traefik-ingress-lb
        name: traefik-ingress-lb
    spec:
      serviceAccountName: traefik-ingress-controller
      terminationGracePeriodSeconds: 60
      hostNetwork: true
      volumes:
      - name: ssl
        secret:
          secretName: traefik-cert
      - name: config
        configMap:
          name: traefik-conf
      containers:
      - image: traefik
        name: traefik-ingress-lb
        volumeMounts:
        - mountPath: "/etc/kubernetes/ssl"
          name: "ssl"
        - mountPath: "/config"
          name: "config"
        resources:
          limits:
            cpu: 200m
            memory: 300Mi
          requests:
            cpu: 100m
            memory: 200Mi
        ports:
        - name: http
          containerPort: 80
          hostPort: 80
        - name: https
          containerPort: 443
          hostPort: 443
        - name: admin
          containerPort: 8080
          hostPort: 8080
        args:
        - --api
        - --kubernetes
        - --configfile=/config/traefik.toml
        - --insecureskipverify      
      nodeSelector:
        edgenode: "true"  #指定部署traefik的主機標簽
---
kind: Service
apiVersion: v1
metadata:
  name: traefik-ingress-service
  namespace: kube-system
spec:
  selector:
    k8s-app: traefik-ingress-lb
  ports:
    - protocol: TCP
      port: 80
      name: web
    - protocol: TCP
      port: 443
      name: https
    - protocol: TCP
      port: 8080
      name: admin
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: traefik-web-ui
  namespace: kube-system
spec:
  rules:
  - host: traefikui.test.com
    http:
      paths:
      - path: /
        backend:
          serviceName: traefik-ingress-service
          servicePort: admin

volumes用來引用創建的secret和configmap,volumeMounts 指定將引用的secret和configmap掛載到什么位置。

5.5.3 檢查創建的traefik ui

[root@node-01 traefik]# kubectl get pods -A |grep trae
kube-system   traefik-ingress-controller-6q7hx        1/1     Running   0          14h
kube-system   traefik-ingress-controller-wgr7d        1/1     Running   0          14h

查看日志,檢查有無報錯
[root@node-01 traefik]# kubectl logs -f traefik-ingress-controller-wgr7d -n kube-system
測試traefik ui能否正常訪問: 

通過本地host測試, 172.19.8.115 traefikui.test.com , 訪問 http://traefikui.test.com   和 https://traefikui.test.com

6 實戰小測

1、client --- (via https) ---> traefik ---- (via http) ---->  services
[root@node-01 testnginx]# cat test-nginx.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 443
---
apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    app: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    app: my-nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-nginx
spec:
  rules:
  - host: test.test.com
    http:
      paths:
      - backend:
          serviceName: my-nginx
          servicePort: 80
        path: /
  tls:
    - hosts:
      - test.test.com

2、client --- (via https) ---> traefik ---- (via https) ---->  services
此處使用k8s dashboard測試,因為dashboard里面只開啟了443端口
假設dashboard已部署完成。此處只需添加ingress文件即可。
[root@node-01 ~]# cat kubernetes-dashboard-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: kube-ui
  namespace: kube-system
spec:
  rules:
  - host: k8sui.ptengine.jp
    http:
      paths:
      - path: '/'
        backend:
          serviceName: kubernetes-dashboard
          servicePort: 443

測試完成。
此處需要注意traefik開啟 --insecureskipverify 否則會出現403報錯。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM