1、kube-router 准备

1.1 kube-router 部署在所以node节点包括vip节点ingress节点

1.2 kube-router 二进制准备

mkdir -p /apps/work/k8s/kube-router
cd /apps/work/k8s/kube-router
wget https://github.com/cloudnativelabs/kube-router/releases/download/v0.3.1/kube-router_0.3.1_linux_amd64.tar.gz
tar -xvf kube-router_0.3.1_linux_amd64.tar.gz
mkdir bin  conf 
mv kube-router bin
rm -rf kube-router_0.3.1_linux_amd64.tar.gz  LICENSE  README.md

2、创建kube-router 访问kube-apiserver 证书

cat << EOF | tee /apps/work/k8s/cfssl/k8s/kube-router.json
{
  "CN": "kube-router",
  "hosts": [""], 
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "GuangDong",
      "L": "GuangZhou",
      "O": "system:masters",
      "OU": "Kubernetes-manual"
    }
  ]
}
EOF

## 生成 kube-router 证书和私钥
cfssl gencert \
        -ca=/apps/work/k8s/cfssl/pki/k8s/k8s-ca.pem \
        -ca-key=/apps/work/k8s/cfssl/pki/k8s/k8s-ca-key.pem \
        -config=/apps/work/k8s/cfssl/ca-config.json \
        -profile=kubernetes \
         /apps/work/k8s/cfssl/k8s/kube-router.json | \
         cfssljson -bare /apps/work/k8s/cfssl/pki/k8s/kube-router

3、生成kube-router.kubeconfig文件

cd /apps/work/k8s/kube-router/conf
KUBE_APISERVER="https://api.k8s.niuke.local:6443"
kubectl config set-cluster kubernetes \
  --certificate-authority=/apps/work/k8s/cfssl/pki/k8s/k8s-ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=kube-router.kubeconfig

    kubectl config set-credentials kube-router \
  --client-certificate=/apps/work/k8s/cfssl/pki/k8s/kube-router.pem \
  --client-key=/apps/work/k8s/cfssl/pki/k8s/kube-router-key.pem \
  --embed-certs=true \
  --kubeconfig=kube-router.kubeconfig

    kubectl config set-context default \
  --cluster=kubernetes \
  --user=kube-router \
  --kubeconfig=kube-router.kubeconfig

kubectl config use-context default --kubeconfig=kube-router.kubeconfig

4、kube-router 一些参数说明

peer-router-ips bgp 路由vip ip 可以是quagga 也可以是硬件路由器支持bgp的
cluster-cidr 容器的ip段 10.48.0.0/12
hostname-override 读取k8s集群kubelet hostname 如果没有就不能启动
peer-router-asns bgp 配置bgp会用到
metrics-path 监控用到
metrics-port 监控端口

5、创建kube-router配置 例:其它节点参考次配置

cd /apps/work/k8s/kube-router/conf
vi kube-router
KUBE_ROUTER_OPTS="--run-router=true \
--run-firewall=true \
--run-service-proxy=true \
--advertise-cluster-ip=true \
--advertise-external-ip=true \
--advertise-loadbalancer-ip=true \
--advertise-pod-cidr=true \
--cluster-asn=64512 \
--peer-router-ips=192.168.3.12 \
--peer-router-asns=64513 \
--metrics-path=/metrics \
--metrics-port=20241 \
--enable-cni=true \
--enable-ibgp=true \
--enable-overlay=true \
--hairpin-mode=true \
--nodeport-bindon-all-ip=true \
--nodes-full-mesh==true \
--enable-pod-egress=true \
--cluster-cidr=10.48.0.0/12 \
--hostname-override=k8s-node-01 \
--kubeconfig=/apps/kube-router/conf/kube-router.kubeconfig \
--v=2"

6、创建kube-router.service

cd  /apps/work/k8s/
vi kube-router.service 
[Unit]
Description=Kubernetes kube-router
After=docker.service
Requires=docker.service

[Service]
LimitNOFILE=1024000
LimitNPROC=1024000
LimitCORE=infinity
LimitMEMLOCK=infinity
EnvironmentFile=-/apps/kube-router/conf/kube-router
ExecStart=/apps/kube-router/bin/kube-router $KUBE_ROUTER_OPTS
Restart=on-failure
KillMode=process

[Install]
WantedBy=multi-user.target

7、授权kube-router 用户访问kube-apiserver

cd  /apps/work/k8s/
vi kube-router.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kube-router
  namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: kube-router
  namespace: kube-system
rules:
  - apiGroups:
    - ""
    resources:
      - namespaces
      - pods
      - services
      - nodes
      - nodes/proxy
      - endpoints
    verbs:
      - list
      - get
      - watch
  - apiGroups:
    - "networking.k8s.io"
    resources:
      - networkpolicies
    verbs:
      - list
      - get
      - watch
  - apiGroups:
    - extensions
    resources:
      - networkpolicies
    verbs:
      - get
      - list
      - watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: kube-router
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kube-router
subjects:
- kind: ServiceAccount
  name: kube-router
  namespace: kube-system

kubectl create -f kube-router.yaml

8、分发kube-router 到node 节点

ansible -i /apps/work/k8s/host node ingress vip -m shell -a "mkdir -p /apps/kube-router"
ansible -i /apps/work/k8s/host node ingress vip -m copy -a "src=kube-router/ dest=/apps/kube-router/"
ansible -i /apps/work/k8s/host node ingress vip -m shell -a "chmod u+x /apps/kube-router/bin/*"
ansible -i /apps/work/k8s/host node ingress vip -m copy -a "src=kube-router.service dest=/usr/lib/systemd/system/"
修改kube-router hostname-override 参数 

9、启动kube-router

ansible -i /apps/work/k8s/host node ingress vip -m shell -a "systemctl daemon-reload"
ansible -i /apps/work/k8s/host node ingress vip -m shell -a " systemctl enable kube-router"
ansible -i /apps/work/k8s/host node ingress vip -m shell -a " systemctl start kube-router"
ansible -i /apps/work/k8s/host node ingress vip -m shell -a " systemctl status kube-router"

10、检查kube-router 是否 自动分配ip

kubectl get nodes -o json | jq '.items[] | .spec'

[root@jenkins kube-router]# kubectl get nodes -o json | jq '.items[] | .spec'
{
  "podCIDR": "10.48.2.0/24"
}
{
  "podCIDR": "10.48.3.0/24"
}
{
  "podCIDR": "10.48.0.0/24"
}
{
  "podCIDR": "10.48.1.0/24"
}
{
  "podCIDR": "10.48.4.0/24"
}
node 节点 执行 ip route
查看路由
ip -a 查看 k8s 集群ip
5: kube-bridge:  mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether c2:63:42:7c:a7:e2 brd ff:ff:ff:ff:ff:ff
    inet 10.48.2.1/24 scope global kube-bridge
       valid_lft forever preferred_lft forever
6: dummy0:  mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether c6:a3:a5:ba:fe:6d brd ff:ff:ff:ff:ff:ff
7: kube-dummy-if:  mtu 1500 qdisc noqueue state UNKNOWN group default 
    link/ether 5a:a7:15:37:97:53 brd ff:ff:ff:ff:ff:ff
    inet 10.64.0.1/32 brd 10.64.0.1 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.234.237/32 brd 10.64.234.237 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.233.162/32 brd 10.64.233.162 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.215.237/32 brd 10.64.215.237 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.0.2/32 brd 10.64.0.2 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.61.191/32 brd 10.64.61.191 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.97.41/32 brd 10.64.97.41 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.53.220/32 brd 10.64.53.220 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.39.166/32 brd 10.64.39.166 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.126.195/32 brd 10.64.126.195 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.219.124/32 brd 10.64.219.124 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.248.238/32 brd 10.64.248.238 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.153.65/32 brd 10.64.153.65 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.76.72/32 brd 10.64.76.72 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.123.141/32 brd 10.64.123.141 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.5.102/32 brd 10.64.5.102 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.174.152/32 brd 10.64.174.152 scope link kube-dummy-if
       valid_lft forever preferred_lft forever
    inet 10.64.140.170/32 brd 10.64.140.170 scope link kube-dummy-if
       valid_lft forever preferred_lft forever

11、创建测试用例测试集群网络是否互联

kubectl run myip --image=cloudnativelabs/whats-my-ip --replicas=3 --port=8080
kubectl expose deployment myip --port=8080 --target-port=8080 --type=NodePort
kubectl get pod -o wide
kubectl get services --all-namespaces
[root@jenkins k8s]# kubectl get services myip -n default                                         
NAME   TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
myip   NodePort   10.64.160.236           8080:39569/TCP   5s
访问集群ip
http://10.64.160.236:8080 或者node ip:39569  访问

12、kube-router 网络隔离与调度算法

网络隔离
#允许所有入口和出口
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
spec:
  podSelector: {}
  ingress:
  - {}
  egress:
  - {}
#禁止所有入口和出口
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
spec:
  podSelector: {}
  policyTypes:
   - Ingress
   - Egress
#开放特定入口和出口
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
spec:
  podSelector: {}
  policyTypes:
  - Egress
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978
Network Routes Controller
①启用hairpin traffic
kubectl annotate service my-service "kube-router.io/service.hairpin="
②启用DSR(DSR将仅适用于外部IP)
kubectl annotate service my-service "kube-router.io/service.dsr=tunnel"
③负载均衡调度算法(默认轮询)
#最少连接
kubectl annotate service my-service "kube-router.io/service.scheduler=lc"
#轮序
kubectl annotate service my-service "kube-router.io/service.scheduler=rr"
#hash
kubectl annotate service my-service "kube-router.io/service.scheduler=sh"
#目标hash
kubectl annotate service myip "kube-router.io/service.scheduler=dh"   --namespace default
修改
kubectl annotate service myip "kube-router.io/service.scheduler=rr" --namespace default  --overwrite

13、 kube-router playbook

[root@jenkins roles]# tree kube-router/
kube-router/
├── defaults
├── files
│   └── bin
│       └── kube-router
├── handlers
├── meta
├── tasks
│   └── main.yml
├── templates
│   ├── conf
│   │   ├── kube-router
│   │   └── kube-router.kubeconfig
│   ├── kube-router.service
│   └── kube-router.service.old
└── vars

9 directories, 6 files
[root@jenkins roles]# 

13.1 kube-route main.yml

- name: create {{ k8s_path }}/kube-router
  shell: mkdir -p {{ k8s_path }}/kube-router/conf
- name: copy kube-router
  copy: src=bin dest={{ k8s_path }}/kube-router/ owner=root group=root mode=755
- name: copy kube-router config
  template: src=conf/{{ item }} dest=/{{ k8s_path }}/kube-router/conf
  with_items:
      - kube-router.kubeconfig
      - kube-router
- name: copy kube-router.service
  template: src=kube-router.service  dest=/usr/lib/systemd/system/
- name: systemctl daemon-reload
  shell: systemctl daemon-reload
- name: systemctl enable kube-router && systemctl start kube-router
  shell: systemctl enable kube-router && systemctl start kube-router

13.2 kube-route conf/kube-router

KUBE_ROUTER_OPTS="--run-router=true \
                  --run-firewall=true \
                  --run-service-proxy=true \
                  --advertise-cluster-ip=true \
                  --advertise-external-ip=true \
                  --cluster-asn=64512 \
                  --peer-router-ips={{ bgp_ip }} \
                  --peer-router-asns=64513 \
                  --metrics-path=/metrics \
                  --metrics-port=20241 \
                  --enable-cni=true \
                  --enable-ibgp=true \
                  --enable-overlay=true \
                  --enable-pod-egress=true \
                  --hairpin-mode=true \
                  --cluster-cidr={{ cluster_cidr }} \
                  --hostname-override={{ ansible_hostname }} \
                  --kubeconfig={{ k8s_path }}/kube-router/conf/kube-router.kubeconfig \
                  --v= {{ level_log }}"

13.3 kube-route kube-router.service

[Unit]
Description=Kubernetes kube-router 
[Service]
LimitNOFILE=1024000
LimitNPROC=1024000
LimitCORE=infinity
LimitMEMLOCK=infinity
EnvironmentFile=-{{ k8s_path }}/kube-router/conf/kube-router
ExecStart={{ k8s_path }}/kube-router/bin/kube-router $KUBE_ROUTER_OPTS
Restart=on-failure
KillMode=process

[Install]
WantedBy=multi-user.target

13.4、 kube-route site.yml

- hosts: all
  user: root
  vars:
    k8s_path: /apps
    k8s_dns: 10.64.0.2
    bgp_ip: 192.168.3.12
    cluster_cidr: 10.48.0.0/12
    level_log: 2
  roles:
    - kube-router

13.5 playbook 安装 kube-router

单机安装
ansible-playbook -i 192.168.4.5, site.yml
批量安装
ansible-playbook -i /apps/work/k8s/host  site.yml

开启hostport 同时使POD 能够访问自己的ClusterIP

#修改 cni 配置
rm -rf /etc/cni/net.d/*
# 创建10-kuberouter.conflist 文件
# "cniVersion":"0.3.0" cni 版本号根据kubelet 支持版本修改
vi /etc/cni/net.d/10-kuberouter.conflist
    {
       "cniVersion":"0.3.0",
       "name":"mynet",
       "plugins":[
          {
             "name":"kubernetes",
             "type":"bridge",
             "bridge":"kube-bridge",
             "isDefaultGateway":true,
             "hairpinMode":true,
             "ipam":{
                "type":"host-local"
             }
          },
          {
             "type":"portmap",
             "capabilities":{
                "snat":true,
                "portMappings":true
             }
          }
       ]
    }

# 修改 kube-router 启动配置文件
# 添加环境变量KUBE_ROUTER_CNI_CONF_FILE
vi kube-router
KUBE_ROUTER_OPTS="--run-router=true \
--run-firewall=true \
--run-service-proxy=true \
--advertise-cluster-ip=true \
--advertise-external-ip=true \
--advertise-loadbalancer-ip=true \
--advertise-pod-cidr=true \
--cluster-asn=64512 \
--peer-router-ips=192.168.3.12 \
--peer-router-asns=64513 \
--metrics-path=/metrics \
--metrics-port=20241 \
--enable-cni=true \
--enable-ibgp=true \
--enable-overlay=true \
--nodeport-bindon-all-ip=true \
--nodes-full-mesh==true \
--enable-pod-egress=true \
--hairpin-mode=true \
--cluster-cidr=10.48.0.0/12 \
--hostname-override=k8s-node-01 \
--kubeconfig=/apps/kube-router/conf/kube-router.kubeconfig \
--v=2"
KUBE_ROUTER_CNI_CONF_FILE="/etc/cni/net.d/10-kuberouter.conflist"
# 重启 kube-router
systemctl restart kube-router
# 查看cni 配置文件是否正常修改  kube-router 不会dump 
[root@node02 bin]# cat /etc/cni/net.d/10-kuberouter.conflist
{"cniVersion":"0.3.0","name":"mynet","plugins":[{"bridge":"kube-bridge","hairpinMode":true,"ipam":{"subnet":"10.48.1.0/24","type":"host-local"},"isDefaultGateway":true,"name":"kubernetes","type":"bridge"},{"capabilities":{"portMappings":true,"snat":true},"type":"portmap"}]}
一切正常hostport  开启成功

下一篇: Kubernetes 生产环境安装部署 基于 Kubernetes v1.14.0 之 CoreDNS部署