上一篇文章,通过二进制包的方式部署了K8S集群,灵活性较强,但是操作繁琐,接下来介绍通过Kubeamd部署K8S集群的方法,该方法操作简单(看目录就能发现操作步骤少了很多),也是官方推荐的K8S集群部署方式。
目录
1 环境要求及初始化
1.1 环境要求
- 3台虚拟机(1个Master,2个Node),操作系统 CentOS7.x_x64
- 硬件配置:2个CPU、2G内存、20G硬盘
- 集群中所有机器之间网络互通
- 可以访问外网,需要拉取镜像(如果不能访问,找一台能访问外网的机器拉取镜像,再通过docker save/load 把镜像转移到目标机器上)
- 禁止swap分区
1.2 环境初始化
(1)基本的操作系统环境初始化配置
#1、关闭 firewalld 防火墙(不让默认创建的网络规则生效):
systemctl stop firewalld
systemctl disable firewalld
#2、关闭selinux(selinux提供了Linux安全机制,但是功能不好用):
sed -i 's/enforcing/disabled/' /etc/selinux/config # 永久
setenforce 0 # 临时
#3、关闭swap(永久关闭需要重启虚拟机):
swapoff -a # 临时
vim /etc/fstab # 永久,把最后一行注释掉即可
#4、设置主机名:
hostnamectl set-hostname kubeadm-master
hostnamectl set-hostname kubeadm-node1
hostnamectl set-hostname kubeadm-node2
#5、在master添加hosts(只在matser节点设置此项,其他操作要在所有节点都执行一遍):
cat >> /etc/hosts << EOF
192.168.200.210 kubeadm-master
192.168.200.211 kubeadm-node1
192.168.200.212 kubeadm-node2
EOF
#6、将桥接的IPv4流量传递到iptables的链(防止丢包):
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# 7、生效
sysctl --system
#8、时间同步:
yum install ntpdate -y
ntpdate time.windows.com
#上述全部操作完后重启所有虚拟机
(2)安装 kubeadm、kubectl、kubelet、Docker(所有节点)
#先添加阿里云YUM源
cat >/etc/yum.repos.d/kubernetes.repo << EOF
[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 install -y kubelet-1.19.0 kubeadm-1.19.0 kubectl-1.19.0
systemctl enable kubelet
#安装yum工具
# sudo yum install -y yum-utils device-mapper-persistent-data lvm2
#设置阿里云镜像
# sudo yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#安装 Docker
sudo yum install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker
上述安装的三个组件介绍如下:
- kubeadm
kubeadm用来部署K8S中的各种组件,且除kubelet组件以外,其余组件都是kubeadm通过容器化方式进行部署的
(1)etcd
(2)master:apiserver、controller-manager、scheduler
(3)node:kubelet、kube-proxy、docker
- kubectl
K8S命令行管理工具
- kubelet
K8S-Node中的组件,由于kubeadm没法将它容器化部署,所有我们手动部署这个组件,由systemd管理。
2 部署 K8S-Master
只在Matser节点中执行如下操作:
#1、创建一个master节点(创建完成后会有一些重要的提示信息,用来执行后续操作)
kubeadm init \
--apiserver-advertise-address=192.168.200.210 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.19.0 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--ignore-preflight-errors=all
#2、按照提示信息执行如下三行:拷贝K8S集群的认证文件到默认路径下
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
#3、执行完过后通过如下指令查看node
kubectl get node
#(非必要操作)如果在kubeadm init的时候出现了错误,那么需要先执行如下指令进行环境清理,再重新执行初始化操作
kubeadm reset
kubeadm 初始化工作做了如下事项,这些事项对应着使用二进制方式进行K8S部署时的各种繁琐操作,在这里kubeadm帮我们完成了:
- [preflight] 环境检查、拉取镜像
- [certs] 生成k8s、etcd证书,证书目录:/etc/kubernetes/pki
- [kubeconfig] 生成kubeconfig文件,用于连接认证
- [kubelet-start] 生成kubelet配置文件,启动kubelet
- [control-plane] 部署管理节点组件,用镜像启动容器。
- [etcd] 部署etcd数据库,用镜像启动容器
- [upload-config] [kubelet] [upload-certs] 上传配置文件到k8s中
- [mark-control-plane] 给管理节点添加一个标签 node-role.kubernetes.io/master='',再添加一个污点[node-role.kubernetes.io/master:NoSchedule]
- [bootstrap-token] 自动为kubelet颁发证书
- [addons] 部署插件,CoreDNS、kube-proxy
指令执行完后,命令行显示如下内容:
移动配置文件的工作已经做完了,按照图中的指引,还需要完成后两项。
由于上图中的一些指引信息后面的操作会用到,这里copy下来(暂不用执行):
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.200.210:6443 --token i6i86c.8rga8zi7yp3xwsdr \
--discovery-token-ca-cert-hash sha256:accabeca75f83ed390ef37ecda7a104e605a1b3936813ecb93bdfdc5bbb8ad1e
此外,查看K8S集群中已经启动的pods:
3 K8S集群中加入Node
(1)让Node节点加入K8S集群
在两台Node机器中分别执行如下操作,将各个Node节点加入到K8S集群中:
kubeadm join 192.168.200.210:6443 --token i6i86c.8rga8zi7yp3xwsdr \
--discovery-token-ca-cert-hash sha256:accabeca75f83ed390ef37ecda7a104e605a1b3936813ecb93bdfdc5bbb8ad1e
注意:上面的token有效期为24小时,过期要在matster机器上执行如下操作(不是必要操作)
$ kubeadm token create
$ kubeadm token list
$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
63bca849e0e01691ae14eab449570284f0c3ddeea590f8da988c07fe2729e924
$ kubeadm join 192.168.200.210:6443 --token nuja6n.o3jrhsffiqs9swnu --discovery-token-ca-cert-hash sha256:63bca849e0e01691ae14eab449570284f0c3ddeea590f8da988c07fe2729e924
或者直接命令快捷生成(不是必要操作):
kubeadm token create --print-join-command
参考:https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-join/
此时查看集群中的Node节点信息,发现Not Ready,这说明还需要配置网络:
(2)部署容器网络
在Master机器上执行如下指令:
#1、安装wget
yum -y install wget
#2、K8S集群中容器网络选择calico,下载
wget https://docs.projectcalico.org/manifests/calico.yaml
#3、修改打开文件
vi calico.yaml
#4、在非编辑模式下输入:/CALICO_IPV4POOL_CIDR,快速锁定到要修改的字段部分
#5、将CALICO_IPV4POOL_CIDR字段的值修改为与先前kubeadm init中指定的一致,如下图
#6、执行安装
kubectl apply -f calico.yaml
这个配置文件中制定pod子网ip要和最开始kubeadm初始化时pod-network-cidr的ip一致!
上面步骤6执行安装之后,查看 K8S-Pod 时发现有些Calico相关的容器没有创建好,这是因为还在安装镜像,稍微等待后如下图(如果状态一直没有ready,就只能手动拉取镜像,而具体拉取哪些镜像通过指令:grep image calico.yaml 查看):
此时再次查看集群中Node节点信息,发现网络已经打通了:
4 部署DashBoard
在Master节点上执行如下操作:
- step1:下载Dashboard的yaml文件
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.3/aio/deploy/recommended.yaml
如果下载失败,请执行以下操作,下载成功请忽略:
#打开文件
sudo vi /etc/hosts
#增加以下的信息到文件中
# GitHub Start
52.74.223.119 github.com
192.30.253.119 gist.github.com
54.169.195.247 api.github.com
185.199.111.153 assets-cdn.github.com
185.199.110.133 raw.githubusercontent.com
151.101.108.133 user-images.githubusercontent.com
151.101.76.133 gist.githubusercontent.com
151.101.76.133 cloud.githubusercontent.com
151.101.76.133 camo.githubusercontent.com
151.101.76.133 avatars0.githubusercontent.com
151.101.76.133 avatars1.githubusercontent.com
151.101.76.133 avatars2.githubusercontent.com
151.101.76.133 avatars3.githubusercontent.com
151.101.76.133 avatars4.githubusercontent.com
151.101.76.133 avatars5.githubusercontent.com
151.101.76.133 avatars6.githubusercontent.com
151.101.76.133 avatars7.githubusercontent.com
151.101.76.133 avatars8.githubusercontent.com
# GitHub End
- step2:修改配置,让外部也能访问Dashboard
#打开刚下载好的这个文件
vi recommended.yaml
#在指定位置新增如下这一行
type: NodePort
- step3:应用
#应用
kubectl apply -f recommended.yaml
#查看kubernetes-dashboard命名空间下的资源
kubectl get pods -n kubernetes-dashboard
- step4:查看端口号(容器服务端口443,对外访问端口31283)
kubectl get pods,svc -n kubernetes-dashboard
- step5:访问
注意要用https进行访问:https://192.168.200.211:31283
此时进入登陆页面,需要用到token:
- step6:创建service account,绑定默认cluster-admin管理员集群角色
# 创建用户
kubectl create serviceaccount dashboard-admin -n kube-system
# 给用户授权
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
# 获取用户Token
kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}')
复制token,进入UI页面:
5 测试
在Matser节点中输入如下指令进行测试:
#创建容器
kubectl create deployment nginx --image=nginx
#暴露应用
kubectl expose deployment nginx --port=80 --type=NodePort
#查看容器(稍等下才能准备好)
kubectl get pod,svc
#CLUSTER-IP是内部访问IP,通过指令:curl [CLUSTER-IP] 在K8S内部访问该容器
#外部访问容器时,IP为任意Node IP,端口号为 kubectl get pod,svc 该指令执行后所展示的端口号(一般都是30xxx)
外部访问容器:
6 K8S网络简介
这里稍微聊一下K8S的网络问题,后续再进行完善
K8s是一个扁平化网络,即所有部署的网络组件都必须满足如下要求:
- 一个Pod一个IP
- 所有的Pod 可以与任何其他Pod 直接通信
- 所有节点可以与所有Pod 直接通信
- Pod 内部获取到的IP 地址与其他Pod 或节点与其通信时的IP 地址是同一个
- 主流网络组件有:Flannel、Calico等
- 对于同一节点下不同容器间的通信,Docker就已经实现了,而引入CNI是为了解决跨主机网络通信的问题。
问题
- K8S集群中分布在不同Node下的容器IP唯一性问题
- 容器IP与Docker主机的对应关系问题
- 如何实现转发
回答
- 给每个的Docker主机分配唯一的IP网段
- 记录好每个的Docker主机所对应的IP网段
- 使用iptables,或者把宿主机作为路由器,配置路由表,实现转发