利用Vagrant创建k8s集群

Vagrant环境

1. 创建Vagrant主机

通过vagrant的Vagrantfile新建三台主机

主机名称 角色 地址
master master 192.168.8.110
node1 node 192.168.8.111
node2 node 192.168.8.112
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
30
31
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

config.vm.define "k8s-01" do |master|
master.vm.box = "centos7"
master.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
vb.cpus = 2
end
master.vm.network "public_network", ip: "192.168.8.110"
master.ssh.insert_key = false
master.vm.hostname = "master"
end

config.vm.define "k8s-02" do |node1|
node1.vm.box = "centos7"
node1.vm.network "public_network", ip: "192.168.8.111"
node1.ssh.insert_key = false
node1.vm.hostname = "node1"
end

config.vm.define "k8s-03" do |node2|
node2.vm.box = "centos7"
node2.vm.network "public_network", ip: "192.168.8.112"
node2.ssh.insert_key = false
node2.vm.hostname = "node2"
end

end

2. 修改主机名

修改三台主机的hosts文件 添加如下信息

1
2
3
192.168.8.110   master
192.168.8.111 node1
192.168.8.112 node2

3. 开启ssh连接

由于vagrant默认无密码密钥验证连接,为了便于管理,建议开启ssh开启密码连接,修改/etc/ssh/sshd_config文件,开启密码验证(记得使用passwd修改密码)

1
2
3
4
5
6
vim /etc/ssh/sshd_config
#开启PasswordAuthentication选项为yes 注释掉为no的选项
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication yes
#PermitEmptyPasswords no
#PasswordAuthentication no

4. 关闭防火墙

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
iptables -F
systemctl stop firewalld
systemctl disable firewalld

# 关闭selinux(关闭后重启生效)
vim /etc/selinux/config
# 修改SELINUX=enforcing选项为disabled
SELINUX=disabled
#开启临时关闭selinux
setenforce 0

# 禁止iptables对bridge数据进行处理(kubeadm初始化时会检测该选项)
## 开启内核模块
modprobe br_netfilter
## 写入配置参数
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
## 立即生效
sysctl -p /etc/sysctl.d/k8s.conf

5. 关闭swap

1
2
# 临时关闭
swapoff -a

6. 安装k8s组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 移除旧版本docker
sudo yum remove docker docker-common docker-selinux docker-engine
# 安装一些依赖
sudo yum install -y yum-utils device-mapper-persistent-data lvm2 wget
# 下载发行版repo文件
sudo wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
# 官方的源速度太慢 把软件仓库地址替换为 TUNA
sudo sed -i 's+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+' /etc/yum.repos.d/docker-ce.repo

# 添加kube组件仓库源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

安装并启动(截止于2019.11.15发表该文,目前k8s支持docker到18.09版本,当前新版本19.X版本安装会导致kubeadm初始化报错)

1
2
3
4
5
6
7
8
9
10
# 刷新索引缓存
sudo yum makecache fast
# 安装软件
yum install -y docker-ce-18.09.9 kubelet kubeadm kubectl
# 启动并自启动
systemctl start docker
systemctl enable docker

systemctl start kubelet
systemctl enable kubelet

注意:上述步骤master和node节点均需操作

集群安装配置

主节点配置

1. 初始化kubeadm

1
kubeadm init --apiserver-advertise-address=192.168.8.110 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.16.0 --pod-network-cidr=10.244.0.0/16

注意: 初始化失败,使用kubeadm reset 进行重置。成功后会生成一串信息,类似kubeadm join --token {token} {master-ip}:6443 --discovery-token-ca-cert-hash sha256:{hash-code} 建议保存。若无法找到该信息,请看下面的操作

--apiserver-advertise-address 指定api地址,一般为master节点

--image-repository 指定镜像仓库

--kubernetes-version 指定k8s版本(截至当前为1.16.0)

--pod-network-cidr 指定flannel网络(默认不要改)

2. 配置kubeconfig

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

3. 安装网络插件flannel

注意: 安装该插件会请求quay.io的镜像,请确保可以正常访问

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
# 先下载配置好后部署[建议使用此]
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
## 修改文件中的所有image标签,将 quay.io 改为可用仓库名称
## 任选[quay.azk8s.cn, quay.mirrors.ustc.edu.cn, quay-mirror.qiniu.com]
## 修改示例:
image: quay.io/coreos/flannel:v0.11.0-amd64 =>
image: quay.azk8s.cn/coreos/flannel:v0.11.0-amd64
# 部署
kubectl apply -f kube-flannel.yml

# 直接部署(可能由于网络原因导致镜像拉取 失败)
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
## 若你发现部署后coredns的pod无法Running,主谋可能就是flannel节点拉取失败,请使用如下方式
## 镜像地址: quay.io/coreos/flannel 截至[19.11.17]最新版本为0.11.0.*
## 先删除上次部署(删除前最好看看pod事件,查看无法启动原因)
kubectl delete -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
## 拉取镜像(参考底部参考链接,从其他可用仓库拉取镜像)
## 模板: docker pull quay.azk8s.cn/xxx/yyy:zzz
## 其他针对quay.io的可用仓库: quay.mirrors.ustc.edu.cn quay-mirror.qiniu.com
## 示例操作如下:
docker pull quay.azk8s.cn/coreos/flannel:v0.11.0-amd64
## 根据上一步将缺失的镜像拉取后,修改tag 其实就是将仓库名称改回来
docker tag quay.azk8s.cn/coreos/flannel:v0.11.0-amd64 quay.io/coreos/flannel:v0.11.0-amd64
# 将缺失的镜像全部拉取下来后 再次部署
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

从节点配置

1. 添加从节点

1
2
3
4
5
6
7
8
9
10
11
# 在需要被添加的从节点(node)上,执行如下一条命令即可
kubeadm join --token {token} {master-ip}:6443 --discovery-token-ca-cert-hash sha256:{hash-code}
# 说明
# token:
# 使用 kubeadm token list 查看可用token列表
# 使用 kubeadm token create 创建一个新的(token过期时使用)
# master-ip
# 填写主节点的ip地址
# hash-code
# 使用以下命令生成:
# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

测试

1. 创建Deployment

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
# 创建nginx配置文件
vim nginx-deployment.yaml
# 文件内容
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
# 部署
kubectl apply -f nginx-deployment.yaml

部署后,我们查看deployment信息

1
2
3
4
5
6
7
8
9
10
11
# 查看所有节点信息
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-59c9f8dff-4n258 1/1 Running 0 20m
nginx-deployment-59c9f8dff-528g8 1/1 Running 0 20m

# 查看更详细的节点信息
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-59c9f8dff-4n258 1/1 Running 0 21m 10.244.2.2 node2 <none> <none>
nginx-deployment-59c9f8dff-528g8 1/1 Running 0 21m 10.244.1.2 node1 <none> <none>

2. 曝露资源

发现deployment被分布在了node1和node2上,尝试曝露服务给Service

1
kubectl expose deployment nginx-deployment --port=80 --type=NodePort

查看曝露的服务,由此,可以开始外网访问了

1
2
3
4
[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 105m
nginx-deployment NodePort 10.1.155.69 <none> 80:30373/TCP 25m

发现对外网曝露的端口是30373,我们可以使用NodePort:30373 进行访问了

浏览器无法访问?

“恭喜你!”,你中招了,你可以互Ping一下各个节点的flannel分配的ip,你会发现节点间无法访问,意味着节点间无法通信!什么原因导致的呢?其实是虚拟机限制,我们需要在部署flannel的时候,修改一下flannel启动参数,设置默认网卡即可.看下面操作

第一步,查看master-IP对应的网卡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@master ~]# ip a
1: lo: ......
inet 127.0.0.1/8 scope host lo
......
2: eth0: ......
inet 10.0.2.15/24 brd 10.0.2.255 scope global noprefixroute dynamic eth0
......
3: eth1: ......
inet 192.168.8.110/24 brd 192.168.8.255 scope global noprefixroute eth1
......
4: docker0: ......
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
......
6: cni0: ......
inet 10.244.0.1/24 scope global cni0
......
9: vethab2f2292@if3: ......
......
10: vethb80eca19@if3: ......
......
11: flannel.1: ......
inet 10.244.0.0/32 scope global flannel.1
......

发现192.168.8.110对应的ip分发网卡是 eth1 记下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 删除部署的flannel
kubectl delete -f kube-flannel.yml
# 修改kube-flannel.yml文件
# 修改spec.template.spec.containers[x].args 字段
# 一般都是x86架构系(amd64)吧 那就修改第一个DaemonSet 大概在180-200行左右
# 找到对应的平台的DaemonSet
# 在 args 下,添加一行 - -- iface=网卡名
# 上面得到我的网卡 eth1 填写上 - --iface=eth1 即可
containers:
- name: kube-flannel
image: quay.io/coreos/flannel:v0.11.0-amd64
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
- --iface=eth1

修改完成之后输入:wq保存退出.重建POD

1
kubectl apply -f kube-flannel.yml

然后再随便找个pod试一下他对应的ip地址,可以看到问题解决了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-59c9f8dff-5vfl9 1/1 Running 0 3h46m 10.244.1.2 node1 <none> <none>
nginx-deployment-59c9f8dff-bl9cd 1/1 Running 0 3h46m 10.244.2.2 node2 <none> <none>
nginx-deployment-59c9f8dff-tb776 1/1 Running 0 3h46m 10.244.2.3 node2 <none> <none>

[root@master ~]# ping 10.244.1.2
PING 10.244.1.2 (10.244.1.2) 56(84) bytes of data.
64 bytes from 10.244.1.2: icmp_seq=1 ttl=63 time=0.793 ms
64 bytes from 10.244.1.2: icmp_seq=2 ttl=63 time=0.942 ms
......

[root@master ~]# ping 10.244.2.2
PING 10.244.2.2 (10.244.2.2) 56(84) bytes of data.
64 bytes from 10.244.2.2: icmp_seq=1 ttl=63 time=0.541 ms
64 bytes from 10.244.2.2: icmp_seq=2 ttl=63 time=0.582 ms
......

# 节点可以访问通

浏览器打开,访问 <NodePort>:Port 可以预见两个节点都可以访问.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 外网访问第一个节点
[root@master ~]# curl -I 192.168.8.111:30373
HTTP/1.1 200 OK
Server: nginx/1.17.5
Date: Sat, 16 Nov 2019 21:38:15 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 22 Oct 2019 14:30:00 GMT
Connection: keep-alive
ETag: "5daf1268-264"
Accept-Ranges: bytes

# 外网访问第二个节点
[root@master ~]# curl -I 192.168.8.112:30373
HTTP/1.1 200 OK
Server: nginx/1.17.5
Date: Sat, 16 Nov 2019 21:39:04 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 22 Oct 2019 14:30:00 GMT
Connection: keep-alive
ETag: "5daf1268-264"
Accept-Ranges: bytes

参考

使用vagrant搭建k8s集群

使用kubeadm创建kubernets集群

烂泥:docker.io、gcr.io、quay.io镜像加速

使用Kubeadm创建k8s集群之节点部署(三十一)

解决k8s无法通过svc访问其他节点pod的问题