# 邊緣節點配置
## 前言
為了配置kubernetes中的traefik ingress的高可用,對于kubernetes集群以外只暴露一個訪問入口,需要使用keepalived排除單點問題。本文參考了[kube-keepalived-vip](https://github.com/kubernetes/contrib/tree/master/keepalived-vip),但并沒有使用容器方式安裝,而是直接在node節點上安裝。
## 定義
首先解釋下什么叫邊緣節點(Edge Node),所謂的邊緣節點即集群內部用來向集群外暴露服務能力的節點,集群外部的服務通過該節點來調用集群內部的服務,邊緣節點是集群內外交流的一個Endpoint。
**邊緣節點要考慮兩個問題**
- 邊緣節點的高可用,不能有單點故障,否則整個kubernetes集群將不可用
- 對外的一致暴露端口,即只能有一個外網訪問IP和端口
## 架構
為了滿足邊緣節點的以上需求,我們使用[keepalived](http://www.keepalived.org/)來實現。
在Kubernetes中添加了service的同時,在DNS中增加一個記錄,這條記錄需要跟ingress中的`host`字段相同,IP地址即VIP的地址,本示例中是`172.20.0.119`,這樣集群外部就可以通過service的DNS名稱來訪問服務了。
選擇Kubernetes的三個node作為邊緣節點,并安裝keepalived,下圖展示了邊緣節點的配置,同時展示了向Kubernetes中添加服務的過程。

## 準備
復用kubernetes測試集群的三臺主機。
172.20.0.113
172.20.0.114
172.20.0.115
## 安裝
使用keepalived管理VIP,VIP是使用IPVS創建的,[IPVS](http://www.linux-vs.org)已經成為linux內核的模塊,不需要安裝
LVS的工作原理請參考:http://www.cnblogs.com/codebean/archive/2011/07/25/2116043.html
不使用鏡像方式安裝了,直接手動安裝,指定三個節點為邊緣節點(Edge node)。
因為我們的測試集群一共只有三個node,所有在在三個node上都要安裝keepalived和ipvsadmin。
```bash
yum install keepalived ipvsadm
```
## 配置說明
需要對原先的traefik ingress進行改造,從以Deployment方式啟動改成DeamonSet。還需要指定一個與node在同一網段的IP地址作為VIP,我們指定成172.20.0.119,配置keepalived前需要先保證這個IP沒有被分配。。
- Traefik以DaemonSet的方式啟動
- 通過nodeSelector選擇邊緣節點
- 通過hostPort暴露端口
- 當前VIP漂移到了172.20.0.115上
- Traefik根據訪問的host和path配置,將流量轉發到相應的service上
## 配置keepalived
參考[基于keepalived 實現VIP轉移,lvs,nginx的高可用](http://limian.blog.51cto.com/7542175/1301776),配置keepalived。
keepalived的官方配置文檔見:http://keepalived.org/pdf/UserGuide.pdf
配置文件`/etc/keepalived/keepalived.conf`文件內容如下:
```ini
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from kaadmin@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
172.20.0.119
}
}
virtual_server 172.20.0.119 80{
delay_loop 6
lb_algo loadbalance
lb_kind DR
nat_mask 255.255.255.0
persistence_timeout 0
protocol TCP
real_server 172.20.0.113 80{
weight 1
TCP_CHECK {
connect_timeout 3
}
}
real_server 172.20.0.114 80{
weight 1
TCP_CHECK {
connect_timeout 3
}
}
real_server 172.20.0.115 80{
weight 1
TCP_CHECK {
connect_timeout 3
}
}
}
```
`Realserver`的IP和端口即traefik供外網訪問的IP和端口。
將以上配置分別拷貝到另外兩臺node的`/etc/keepalived`目錄下。
我們使用轉發效率最高的`lb_kind DR`直接路由方式轉發,使用TCP_CHECK來檢測real_server的health。
設置keepalived為開機自啟動:
```bash
chkconfig keepalived on
```
**啟動keepalived**
```
systemctl start keepalived
```
三臺node都啟動了keepalived后,觀察eth0的IP,會在三臺node的某一臺上發現一個VIP是172.20.0.119。
```bash
$ ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether f4:e9:d4:9f:6b:a0 brd ff:ff:ff:ff:ff:ff
inet 172.20.0.115/17 brd 172.20.127.255 scope global eth0
valid_lft forever preferred_lft forever
inet 172.20.0.119/32 scope global eth0
valid_lft forever preferred_lft forever
```
關掉擁有這個VIP主機上的keepalived,觀察VIP是否漂移到了另外兩臺主機的其中之一上。
## 改造Traefik
在這之前我們啟動的traefik使用的是deployment,只啟動了一個pod,無法保證高可用(即需要將pod固定在某一臺主機上,這樣才能對外提供一個唯一的訪問地址),現在使用了keepalived就可以通過VIP來訪問traefik,同時啟動多個traefik的pod保證高可用。
配置文件`traefik.yaml`內容如下:
```yaml
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: 8580
hostPort: 8580
args:
- --web
- --web.address=:8580
- --kubernetes
nodeSelector:
edgenode: "true"
```
注意,我們使用了`nodeSelector`選擇邊緣節點來調度traefik-ingress-lb運行在它上面,所有你需要使用:
```
kubectl label nodes 172.20.0.113 edgenode=true
kubectl label nodes 172.20.0.114 edgenode=true
kubectl label nodes 172.20.0.115 edgenode=true
```
給三個node打標簽。
查看DaemonSet的啟動情況:
```Bash
$ kubectl -n kube-system get ds
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE-SELECTOR AGE
traefik-ingress-lb 3 3 3 3 3 edgenode=true 2h
```
現在就可以在外網通過172.20.0.119:80來訪問到traefik ingress了。
## 使用域名訪問Kubernetes中的服務
現在我們已經部署了以下服務:
- 三個邊緣節點,使用Traefik作為Ingress controller
- 使用keepalived做的VIP(虛擬IP)172.20.0.119
這樣在訪問該IP的時候通過指定不同的`Host`來路由到kubernetes后端服務。這種方式訪問每個Service時都需要指定`Host`,而同一個項目中的服務一般會在同一個Ingress中配置,使用`Path`來區分Service已經足夠,這時候只要為VIP(172.20.0.119)來配置一個域名,所有的外部訪問直接通過該域名來訪問即可。
如下圖所示:

## 參考
- [kube-keepalived-vip](https://github.com/kubernetes/contrib/tree/master/keepalived-vip)
- http://www.keepalived.org/
- [keepalived工作原理與配置說明](http://outofmemory.cn/wiki/keepalived-configuration)
- [LVS簡介及使用](http://www.cnblogs.com/codebean/archive/2011/07/25/2116043.html)
- [基于keepalived 實現VIP轉移,lvs,nginx的高可用](http://limian.blog.51cto.com/7542175/1301776)
- 序言
- 云原生
- 云原生(Cloud Native)的定義
- CNCF - 云原生計算基金會簡介
- CNCF章程
- 云原生的設計哲學
- Play with Kubernetes
- 快速部署一個云原生本地實驗環境
- Kubernetes與云原生應用概覽
- 云原生應用之路——從Kubernetes到Cloud Native
- 云原生編程語言
- 云原生編程語言Ballerina
- 云原生編程語言Pulumi
- 云原生的未來
- Kubernetes架構
- 設計理念
- Etcd解析
- 開放接口
- CRI - Container Runtime Interface(容器運行時接口)
- CNI - Container Network Interface(容器網絡接口)
- CSI - Container Storage Interface(容器存儲接口)
- Kubernetes中的網絡
- Kubernetes中的網絡解析——以flannel為例
- Kubernetes中的網絡解析——以calico為例
- 具備API感知的網絡和安全性管理開源軟件Cilium
- Cilium架構設計與概念解析
- 資源對象與基本概念解析
- Pod狀態與生命周期管理
- Pod概覽
- Pod解析
- Init容器
- Pause容器
- Pod安全策略
- Pod的生命周期
- Pod Hook
- Pod Preset
- Pod中斷與PDB(Pod中斷預算)
- 集群資源管理
- Node
- Namespace
- Label
- Annotation
- Taint和Toleration(污點和容忍)
- 垃圾收集
- 控制器
- Deployment
- StatefulSet
- DaemonSet
- ReplicationController和ReplicaSet
- Job
- CronJob
- Horizontal Pod Autoscaling
- 自定義指標HPA
- 準入控制器(Admission Controller)
- 服務發現
- Service
- Ingress
- Traefik Ingress Controller
- 身份與權限控制
- ServiceAccount
- RBAC——基于角色的訪問控制
- NetworkPolicy
- 存儲
- Secret
- ConfigMap
- ConfigMap的熱更新
- Volume
- Persistent Volume(持久化卷)
- Storage Class
- 本地持久化存儲
- 集群擴展
- 使用自定義資源擴展API
- 使用CRD擴展Kubernetes API
- Aggregated API Server
- APIService
- Service Catalog
- 資源調度
- QoS(服務質量等級)
- 用戶指南
- 資源對象配置
- 配置Pod的liveness和readiness探針
- 配置Pod的Service Account
- Secret配置
- 管理namespace中的資源配額
- 命令使用
- Docker用戶過度到kubectl命令行指南
- kubectl命令概覽
- kubectl命令技巧大全
- 使用etcdctl訪問kubernetes數據
- 集群安全性管理
- 管理集群中的TLS
- kubelet的認證授權
- TLS bootstrap
- 創建用戶認證授權的kubeconfig文件
- IP偽裝代理
- 使用kubeconfig或token進行用戶身份認證
- Kubernetes中的用戶與身份認證授權
- Kubernetes集群安全性配置最佳實踐
- 訪問Kubernetes集群
- 訪問集群
- 使用kubeconfig文件配置跨集群認證
- 通過端口轉發訪問集群中的應用程序
- 使用service訪問群集中的應用程序
- 從外部訪問Kubernetes中的Pod
- Cabin - Kubernetes手機客戶端
- Kubernetic - Kubernetes桌面客戶端
- Kubernator - 更底層的Kubernetes UI
- 在Kubernetes中開發部署應用
- 適用于kubernetes的應用開發部署流程
- 遷移傳統應用到Kubernetes中——以Hadoop YARN為例
- 最佳實踐概覽
- 在CentOS上部署Kubernetes集群
- 創建TLS證書和秘鑰
- 創建kubeconfig文件
- 創建高可用etcd集群
- 安裝kubectl命令行工具
- 部署master節點
- 安裝flannel網絡插件
- 部署node節點
- 安裝kubedns插件
- 安裝dashboard插件
- 安裝heapster插件
- 安裝EFK插件
- 生產級的Kubernetes簡化管理工具kubeadm
- 使用kubeadm在Ubuntu Server 16.04上快速構建測試集群
- 服務發現與負載均衡
- 安裝Traefik ingress
- 分布式負載測試
- 網絡和集群性能測試
- 邊緣節點配置
- 安裝Nginx ingress
- 安裝配置DNS
- 安裝配置Kube-dns
- 安裝配置CoreDNS
- 運維管理
- Master節點高可用
- 服務滾動升級
- 應用日志收集
- 配置最佳實踐
- 集群及應用監控
- 數據持久化問題
- 管理容器的計算資源
- 集群聯邦
- 存儲管理
- GlusterFS
- 使用GlusterFS做持久化存儲
- 使用Heketi作為Kubernetes的持久存儲GlusterFS的external provisioner
- 在OpenShift中使用GlusterFS做持久化存儲
- GlusterD-2.0
- Ceph
- 用Helm托管安裝Ceph集群并提供后端存儲
- 使用Ceph做持久化存儲
- 使用rbd-provisioner提供rbd持久化存儲
- OpenEBS
- 使用OpenEBS做持久化存儲
- Rook
- NFS
- 利用NFS動態提供Kubernetes后端存儲卷
- 集群與應用監控
- Heapster
- 使用Heapster獲取集群和對象的metric數據
- Prometheus
- 使用Prometheus監控kubernetes集群
- Prometheus查詢語言PromQL使用說明
- 使用Vistio監控Istio服務網格中的流量
- 分布式跟蹤
- OpenTracing
- 服務編排管理
- 使用Helm管理Kubernetes應用
- 構建私有Chart倉庫
- 持續集成與發布
- 使用Jenkins進行持續集成與發布
- 使用Drone進行持續集成與發布
- 更新與升級
- 手動升級Kubernetes集群
- 升級dashboard
- 領域應用概覽
- 微服務架構
- 微服務中的服務發現
- 使用Java構建微服務并發布到Kubernetes平臺
- Spring Boot快速開始指南
- Service Mesh 服務網格
- 企業級服務網格架構
- Service Mesh基礎
- Service Mesh技術對比
- 采納和演進
- 定制和集成
- 總結
- Istio
- 安裝并試用Istio service mesh
- 配置請求的路由規則
- 安裝和拓展Istio service mesh
- 集成虛擬機
- Istio中sidecar的注入規范及示例
- 如何參與Istio社區及注意事項
- Istio教程
- Istio免費學習資源匯總
- 深入理解Istio Service Mesh中的Envoy Sidecar注入與流量劫持
- 深入理解Istio Service Mesh中的Envoy Sidecar代理的路由轉發
- Linkerd
- Linkerd 使用指南
- Conduit
- Condiut概覽
- 安裝Conduit
- Envoy
- Envoy的架構與基本術語
- Envoy作為前端代理
- Envoy mesh教程
- SOFAMesh
- SOFAMesh中的Dubbo on x-protocol
- SOFAMosn
- 使用 SOFAMosn 構建 SOFAMesh
- 大數據
- Spark standalone on Kubernetes
- 運行支持Kubernetes原生調度的Spark程序
- Serverless架構
- 理解Serverless
- FaaS-函數即服務
- OpenFaaS快速入門指南
- 邊緣計算
- 人工智能