环境准备
3个节点,centos7,内核3.0
设置静态ip和主机名(分别是master,node1,node2):
注意:这里提个醒,因为每个人环境不同,设置的网关效果不一样,有的人设置这个GATEWAY为虚拟网络编辑器中的nat设置显示的192.168.x.2,可能会有个问题就是后续的coredns启动运行成功,但是查看日志会发现io/timeout的错误,创建的pod也无法ping通外网(那么如果应用pod是需要ping外网的那服务就有问题了),稳妥起见,建议你将GATEWAY改为公网上的dns服务器,可以百度搜索你附近的dns服务器,或者直接用8.8.8.8这个
(宿主机的/etc/resolv.conf建议方多几个dns服务器,比如两行nameserver,第一行8.8.8.8,第二行用虚拟机的网格192.168.23.2)
(插一点,要修改coredns的配置,主要修改它的cm,和deploy,kubeadm部署的coredns使用的dnsPolicy不是默认的ClusterFirst,而是Default,对于其余的pod个人建议使用ClusterFirst,你可以在后续部署了coredns后自己选择修改,看个人意愿,用edit修改deploy的dnsPolicy即可)
其他两个节点类似
(为了方便配置这边使用了mobaX,你也可以使用ansible)
域名解析:
关闭防火墙和selinux:
[root@master ~]# systemctl disable firewalld --now
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@master ~]# setenforce 0
[root@master ~]# sed -ir '/^SELINUX=/c SELINUX=disabled' /etc/selinux/config
开启内核 ipv4 转发需要加载 br_netfilter 模块,所以加载下该模块
modprobe br_netfilter
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
bridge-nf 使得 netfilter 可以对 Linux 网桥上的 IPv4/ARP/IPv6 包过滤。比如,设置net.bridge.bridge-nf-call-iptables=1后,二层的网桥在转发包时也会被 iptables的 FORWARD 规则所过滤。常用的选项包括:
net.bridge.bridge-nf-call-arptables:是否在 arptables 的 FORWARD 中过滤网桥的 ARP 包
net.bridge.bridge-nf-call-ip6tables:是否在 ip6tables 链中过滤 IPv6 包
net.bridge.bridge-nf-call-iptables:是否在 iptables 链中过滤 IPv4 包
net.bridge.bridge-nf-filter-vlan-tagged:是否在 iptables/arptables 中过滤打了 vlan 标签的包。
开启ipvs:
[root@master ~]# cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
[root@master ~]# chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
nf_conntrack_ipv4 15053 0
nf_defrag_ipv4 12729 1 nf_conntrack_ipv4
ip_vs_sh 12688 0
ip_vs_wrr 12697 0
ip_vs_rr 12600 0
ip_vs 145458 6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
nf_conntrack 139264 2 ip_vs,nf_conntrack_ipv4
libcrc32c 12644 3 xfs,ip_vs,nf_conntrack
上面脚本创建了的/etc/sysconfig/modules/ipvs.modules文件,保证在节点重启后能自动加载所需模块。使用lsmod | grep -e ip_vs -e nf_conntrack_ipv4命令查看是否已经正确加载所需的内核模块。
安装ipset和用于查看ipvs规则的管理工具ipvsadm:
yum install ipset ipvsadm -y
同步服务器时间:
yum install chrony -y
systemctl enable chronyd
systemctl start chronyd
chronyc sources
关闭swap:
[root@master ~]# swapoff -a
[root@master ~]# free
total used free shared buff/cache available
Mem: 3861288 935552 869172 50696 2056564 2613076
Swap: 0 0 0
[root@master ~]# sed -ir '/ swap / s/^\(.*\)$/#\1/' /etc/fstab
swappiness 参数调整,修改/etc/sysctl.d/k8s.conf添加下面一行:
vm.swappiness=0
动态修改内核参数,不用重启
sysctl -p /etc/sysctl.d/k8s.conf
安装docker
yum install -y yum-utils device-mapper-persistent-data lvm2
配置阿里的docker源
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
配置阿里的centos的yum源
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
(wget -O指定文件存放位置,可以替换覆盖)
yum repolist
列出docker-ce的版本
yum list docker-ce --showduplicates(list,search,info,provides)
yum install -y docker-ce-20.10.10
设置阿里云的docker镜像加速器:
创建目录,(docker启动后一般会自动创建这个目录,这里还未开启,另外daemon.json也算是docker的配置文件,但有时候需要自己手动创建)
mkdir -p /etc/docker
以下内容写入daemon.json文件:
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"registry-mirrors" : [
"https://7uavyeqm.mirror.aliyuncs.com"
]
}
systemctl enable docker --now
注意使用自己的镜像加速器地址,这里的cgroupdriver使用systemd,采用的容器运行时是docker,容器运行时的cgroupdriver要和kubelet一致,kubelet的cgroupdriver默认是systemd
安装kubeadm,kubelet,kubectl
设置阿里源:
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=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
关掉包验证
yum repolist
yum list kubeadm --showduplicates
--disableexcludes 禁掉除了kubernetes之外的别的仓库
yum install -y kubelet-1.20.10 kubeadm-1.20.10 kubectl-1.20.10 --disableexcludes=kubernetes
kubeadm version
systemctl enable --now kubelet
初始化集群
上面的操作是kubernetes集群全部节点都要,接下来初始化kubernetes只在master节点操作
导出初始化文件:
kubeadm config print init-defaults > kubeadm.yaml
查看初始化加群所需的镜像:
[root@master ~]# kubeadm config images list
I0403 13:09:52.119954 69143 version.go:254] remote version is much newer: v1 .23.5; falling back to: stable-1.20
k8s.gcr.io/kube-apiserver:v1.20.15
k8s.gcr.io/kube-controller-manager:v1.20.15
k8s.gcr.io/kube-scheduler:v1.20.15
k8s.gcr.io/kube-proxy:v1.20.15
k8s.gcr.io/pause:3.2
k8s.gcr.io/etcd:3.4.13-0
k8s.gcr.io/coredns:1.7.0
无非就是要用到这些镜像,k8s.gcr.io下载不了就去阿里云或者docker.io下载对应版本的镜像在tag成上述的完整镜像名
注意这里是默认的镜像源,如果修改了kubeadm中中的image源,需要kubeadm config images list --config kubeadm.yaml,如下
vim kubeadm.yaml
修改成一下:
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 192.168.23.172 #内网ip,分清集群内部使用的网卡或网络接口,可以参考/etc/hosts
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock #使用docker这个cri
name: master #master节点,注意名称与master节点的主机名一致
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers #使用阿里镜像源来下载镜像
kind: ClusterConfiguration
kubernetesVersion: v1.20.0
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
podSubnet: 10.244.0.0/16 # Pod 网段,flannel插件需要使用这个网段(cni,flanal都是这个podsubnet内)
scheduler: {}
--- #加入一个kubeproxyconfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs # kube-proxy 模式
可以先下载下对应的镜像
kubeadm config images pull --config kubeadm.yaml
[root@master ~]# kubeadm config images pull --config kubeadm.yaml
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.20.0
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.20.0
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.20.0
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.20.0
[config/images] Pulled registry.aliyuncs.com/google_containers/pause:3.2
[config/images] Pulled registry.aliyuncs.com/google_containers/etcd:3.4.13-0
[config/images] Pulled registry.aliyuncs.com/google_containers/coredns:1.7.0
初始化集群
kubeadm init --config kubeadm.yaml
[root@master ~]# mkdir -p $HOME/.kube 每个节点
[root@master ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@master ~]# chown $(id -u):$(id -g) $HOME/.kube/config
[root@master ~]# scp ~/.kube/config 192.168.23.136:/root/.kube/config
[root@master ~]# scp ~/.kube/config 192.168.23.137:/root/.kube/config
node1:
kubeadm join 192.168.23.172:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:a58c66f8fac694ce2203d154ea4bf88fdbee627f6bd3b209195f19919dc10113
node2:
kubeadm join 192.168.23.172:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:a58c66f8fac694ce2203d154ea4bf88fdbee627f6bd3b209195f19919dc10113
如果忘记了上面的 join 命令可以使用命令 kubeadm token create --print-join-command 重新获取。
kubectl get nodes
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master NotReady control-plane,master 25m v1.20.10
node1 NotReady <none> 67s v1.20.10
node2 NotReady <none> 62s v1.20.10
安装flannel网络插件
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
cat /etc/hosts
[root@master ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.23.172 master
192.168.23.136 node1
192.168.23.137 node2
185.199.111.133 raw.githubusercontent.com
vim kube-flannel.yml修改
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
- --iface=ens33 # 如果是多网卡的话,指定内网网卡的名称
kubectl apply -f kube-flannel.yml
[root@master ~]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-7f89b7bc75-8s84s 1/1 Running 0 44m
coredns-7f89b7bc75-tncxx 1/1 Running 0 44m
etcd-master 1/1 Running 0 44m
kube-apiserver-master 1/1 Running 0 44m
kube-controller-manager-master 1/1 Running 0 44m
kube-flannel-ds-fcwb9 1/1 Running 0 5m27s
kube-flannel-ds-g54nx 1/1 Running 0 5m27s
kube-flannel-ds-lbqc6 1/1 Running 0 5m27s
kube-proxy-7cfns 1/1 Running 0 20m
kube-proxy-cr2kf 1/1 Running 0 20m
kube-proxy-x5f2b 1/1 Running 0 44m
kube-scheduler-master 1/1 Running 0 44m
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane,master 46m v1.20.10
node1 Ready <none> 21m v1.20.10
node2 Ready <none> 21m v1.20.10
当我们部署完网络插件后执行 ifconfig 命令,正常会看到新增的cni0与flannel1这两个虚拟设备,但是如果没有看到cni0这个设备也不用太担心,我们可以观察/var/lib/cni目录是否存在,如果不存在并不是说部署有问题,而是该节点上暂时还没有应用运行,我们只需要在该节点上运行一个 Pod 就可以看到该目录会被创建,并且cni0设备也会被创建出来。
Dashboard
顺便安装kubernetes的图形化ui,实际上少用
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.4/aio/deploy/recommended.yaml
vim recommended.yaml
......
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
ports:
- port: 443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard
type: NodePort # 加上type=NodePort变成NodePort类型的服务,这样集群外的主机也能访
......
apply即可
新版本的 Dashboard 会被默认安装在 kubernetes-dashboard 这个命名空间下面(kubectl get ns)
记住使用 https,Chrome 不生效可以使用Firefox 测试,如果没有 Firefox 下面打不开页面,可以点击页面中的信任证书即可
然后就是登录
创建一个具有全局所有权限的用户来登录 Dashboard:(admin.yaml)
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: admin
roleRef:
kind: ClusterRole #clusterrole不是命名空间级别的,有许多已经存在的clusterrole
name: cluster-admin #这里直接用cluster-admin这个clusterrole
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: admin
namespace: kubernetes-dashboard
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin
namespace: kubernetes-dashboard
直接创建:
$ kubectl apply -f admin.yaml
$ kubectl get secret -n kubernetes-dashboard|grep admin-token
admin-token-lwmmx kubernetes.io/service-account-token 3 1d
$ kubectl get secret admin-token-lwmmx -o jsonpath={.data.token} -n kubernetes-dashboard |base64 -d# 会生成一串很长的base64后的字符串
然后用上面的 base64 解码后的字符串作为 token 登录 Dashboard 即可
节点重置
如果部署过程出错,可以进行一下操作
kubeadm reset
ifconfig cni0 down && ip link delete cni0
ifconfig flannel.1 down && ip link delete flannel.1
rm -rf /var/lib/cni/
注意kubeadm reset,以后再集群中使用时,节点有问题是在不行可以考虑使用kubeadm reset,但是master节点要谨慎,尽量不要使用kubeadm reset。
记录一个坑,6443端口的错误
The connection to the server 192.168.23.178:6443 was refused - did you specify the right host or port?
如果你在部署集群是daemo.json有错,或者说设置的内容不完整,集群开了,这时候你又去该docker.json,就算没有该出语法错误,但你比如修改了了log_file等等的设置,可能于集群运行起来后默认的配置不同,这时候很容易出现这个错误,这时候建议你恢复会之前的daemon.json配置,另外的daemon.json为空对docker来说也是种错误,所以建议一开始就设置好daemon.json,尽量少改动,该了这个文件,可能集群的配置也得手动修改
当然出现上述这个问题的情况不止这个,百度上有出现这个错误的各种记录和解决方法