用 kubeadm 安装 k8s 集群
顺便装个 Calico / Flannel
This post is just for recording which holes I have stepped into while initing k8s.

the very begining

1
Google k8s

install docker(PLZ google docker)

1
2
yum install -y docker
systemctl enable docker && systemctl start docker

install kubeadm

1
2
3
4
5
6
7
8
9
10
11
12
13
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg
https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
setenforce 0
yum install -y kubelet kubeadm kubectl
systemctl enable kubelet && systemctl start kubelet

configure

禁用 SELinux

不熟悉 SELinux, 还是先关为敬.

1
setenforce 0

net.bridge.bridge-nf-call-iptables=1 (RHEL/CentOS 7 可能会遇到)(docker info 中也会有提示)

流经网桥(bridge)的包是否走 iptables. 值为 0 会将流量 bypassed.

1
2
3
4
5
cat <<EOF >  /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system

kubelet cgroup-driver

默认的 kubelet cgroup-driver 默认是 systemd, 而 docker 默认是 cgroupfs, 两者不匹配. 下面命令修改 kubelet 的 cgroups 配置.

1
sed -i 's/--cgroup-driver=systemd/--cgroup-driver=cgroupfs/g' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

kubeadm init 部分配置项目(注意也不要和 docker 的网段重复)

  1. –pod-network-cidr
    配置 pod CIDR, 不与主机所在网段重复, 默认 192.168.0.0/16

  2. –service-cidr
    配置 service CIDR, 不与 pod CIDR 重复, 默认 10.96.0.0/12

kubectl setup

使用 kubeadm init 集群就创建好了, 获取集群信息会需要用 kubectl.

/etc/kubernetes/admin.conf

该文件夹是 kubectl 请求 kube-apiserver 使用的证书和 key.

1
alias k='kubectl --kubeconfig=/etc/kubernetes/admin.conf'

或者给某个用户下的权限

1
2
3
4
mv  $HOME/.kube $HOME/.kube.bak
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

node-role.kubernetes.io/master-

安装好后节点, kubectl describe node 可以看到 Taints: node-role.kubernetes.io/master:NoSchedule. 除非 podSpec 中指明了可以容忍(toleration)该污染, 否则节点集群, 许多 yaml 无法部署.
下面命令去掉对所有集群节点的 taint.

1
kubectl taint nodes --all node-role.kubernetes.io/master-

事已至此

  1. k8s 的大部分组件安装完成, 可以使用 kubectl 查看系统组件的状态.
  2. k get all --all-namespaces 可以看到 kube-system deploy/kube-dns 并没有 AVAILABLE, 该 deployment 需要 CNI plugin 安装完成后才能部署完成.

The network must be deployed before any applications. Also, kube-dns, a helper service, will not start up before a network is installed. kubeadm only supports Container Network Interface (CNI) based networks (and does not support kubenet).

kubeadm reset

重置, 会删除 /etc/kubernetes/.

CNI

k8s 下网络通信需要 Container Network Interface (CNI) based networks, 且只能安装一个 CNI(kubeadm 不支持 kubenet), 可选的有 Calico, Canal, Flannel, Kube-router, Romana, Weave Net 等.

注意

CNI 0.3.0 之后支持 multi-plugin, 链式调用 CNI plugin.

Calico

  1. Calico v2.6 是用了 BGP(https://en.wikipedia.org/wiki/Border_Gateway_Protocol) 协议交换集群主机路由信息(pod 的路由信息), 来实现 pod 之间互通, 每台主机相当于 BGP 中的边界路由, 负责 EndPoint(k8s 下为各个 pod) 之间路由在主机之间传递/交换.
  2. 交换 BGP 协议使用的某个上古项目. The BIRD Internet Routing Daemon
  3. Calico 可选 IP-in-IP 的模式, always/cross-subnet/off. 这是种 overlay 方式, 即 pod 之间的流量会带有两个 IP 头部, outer IP header 的 src/dst 写的都是主机 IP, 所以该模式在三层可达(IP 可通)的网络内即可使用. 但是性能会是非 IP-in-IP 模式的 70%(自测的) 不到.
  4. 在 IP-in-IP 为 off 或者为 cross-subnet 的同网段 pod 之间连接, 其性能 非常接近 原生性能, 因为 package 直接通过主机上写的静态路由到了另外一个主机上, 并没有被解包和拆包.
  5. 依据 BGP 协议, 所有主机都充当路由器互相交换路由, 形成 full-mesh, 会占用主机较多资源, 网络上 BGP 协议占用的流量也可观, 所以会有一种部署个别 Router Reflector(RR) 的方式. Configuring BIRD as a BGP Route Reflector, Calico BIRD Route Reflector container

install

!! 如果之前 kubeadm init 指定了 --pod-network-cidr, 那么需要修改 yaml 文件中的环境变量 CALICO_IPV4POOL_CIDR, 以及关于 IP-in-IP 的配置 CALICO_IPV4POOL_IPIP

1
kubectl apply -f https://docs.projectcalico.org/v2.6/getting-started/kubernetes/installation/hosted/kubeadm/1.6/calico.yaml

这之后

kube-dns 终于 running 了.

uninstall

calico yaml 使用了 etcd, 挂载了主机目录 /var/etcd, 删除的时候记得一并删除, or else 下次安装会使用之前的配置.

Flannel

TODO

Examples (deployment && service)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: first-app
labels:
app: first-app
spec:
template:
metadata:
name: first-app
labels:
app: first-app
spec:
containers:
- name: first-app
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: first-app
spec:
type: NodePort
ports:
- port: 80
selector:
app: first-app

Reference

Installing kubeadm
Using kubeadm to Create a Cluster