kubeadm方式部署K8S1.20单Master集群
作者 | 刘畅 |
时间 | 2021-08-24 |
目录
1.1 生产环境可部署Kubernetes集群的两种方式 1
2 安装kubeadm/kubelet/kubectl 4
3.3 拷贝kubectl使用的连接k8s认证文件到默认路径 6
5.2 修改CALICO_IPV4POOL_CIDR 7
8.2 安装containerd(linux) 12
8.4 配置kubelet使用containerd 13
9.1 k8s删除一直处于terminating状态的pod 15
9.2 无法访问k8s.gcr.io的解决办法 15
1 架构说明
1.1 生产环境可部署Kubernetes集群的两种方式
1 kubeadm部署
(1) Kubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。这里采用kubeadm搭建集群。
(2)
kubeadm工具功能
kubeadm
init # 初始化一个Master节点
kubeadm
join # 将工作节点加入集群
kubeadm
upgrade # 升级K8s版本
kubeadm
token # 管理 kubeadm join 使用的令牌
kubeadm
reset # 清空 kubeadm init 或者 kubeadm join 对主机所做的任何更改
kubeadm
version # 打印 kubeadm 版本
kubeadm
alpha # 预览可用的新功能
2二进制包部署
从github下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。
1.2 准备环境
1 服务器要求
建议最小硬件配置:核CPU、2G内存、30G硬盘
服务器最好可以访问外网,会有从网上拉取镜像需求,如果服务器不能上网,需要提前下载对应镜像并导入节点。
2 服务器规划
操作系统: CentOS7.5
主机名 | IP | 软件 |
k8s-master1 (2核4G) | 主网卡eth1: 172.16.1.81 | docker-ce-19.03.9、kubernetes-1.20 |
k8s-node1 (4核8G) | 主网卡eth1: 172.16.1.83 | docker-ce-19.03.9、kubernetes-1.20 |
3 架构图
1.3 操作系统初始化配置
在172.16.1.81、83节点上操作
(1) 关闭防火墙
#
systemctl stop firewalld
#
systemctl disable firewalld
(2)
关闭selinux
#
sed -i 's/enforcing/disabled/' /etc/selinux/config # 永久
#
setenforce 0 临时
(3)
关闭swap
#
swapoff -a # 临时
#
sed -ri 's/.*swap.*/#&/' /etc/fstab # 永久
(4)
在master添加hosts
cat
>> /etc/hosts << EOF
172.16.1.81
k8s-master1
172.16.1.83
k8s-node1
EOF
(5)
将桥接的IPv4流量传递到iptables的链
#
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables
= 1
net.bridge.bridge-nf-call-iptables
= 1
EOF
#
sysctl --system # 生效,手动加载所有的配置文件
(6)
时间同步
#
yum install ntpdate -y
#
ntpdate ntp.aliyun.com
# crontab
-e
#
crontab -l
*/5
* * * * /usr/sbin/ntpdate ntp.aliyun.com &>/dev/null
(7)
部署docker
这里使用Docker作为容器引擎,也可以换成别的,例如containerd。
1)
安装依赖包
#
yum install -y yum-utils device-mapper-persistent-data lvm2
2)
添加Docker软件包源
#
yum-config-manager \
--add-repo
\
https://download.docker.com/linux/centos/docker-ce.repo3)
更新为阿里云的源
#
wget -O /etc/yum.repos.d/docker-ce.repo
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
4)
清理源缓存
#
yum clean all
5)
安装指定版本的Docker CE
#
yum list docker-ce --showduplicates
| sort -r
# yum
list docker-ce-cli --showduplicates | sort -r
#
yum install docker-ce-19.03.9-3.el7 docker-ce-cli-19.03.9-3.el7
-y
6)
启动Docker服务并设置开机启动
#
systemctl start docker
#
systemctl enable docker
# docker
version # 可以看到docker客户端和服务端都是同一个版本
# docker
info
7)
添加阿里云的镜像仓库
#
mkdir -p /etc/docker
#
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors":
["https://b1cx9cn7.mirror.aliyuncs.com"]
}
EOF
8)
重启docker
#
systemctl daemon-reload
#
systemctl restart docker
(8)
增加iptables
conntrack
表大小,防止iptables性能不佳
参考网站: https://docs.projectcalico.org/maintenance/troubleshoot/troubleshooting#configure-networkmanager
# sysctl -w
net.netfilter.nf_conntrack_max=1000000
#
echo "net.netfilter.nf_conntrack_max=1000000" >>
/etc/sysctl.conf
(9)
设置容器运行时和kubelet使用systemd作为cgroup驱动
1) 编辑"/etc/docker/daemon.json"文件,追加"exec-opts"配置。
{
"exec-opts":
["native.cgroupdriver=systemd"]
}
2) 重启docker
# systemctl
daemon-reload
# systemctl
restart docker
3) 验证配置生效
#
docker info | grep Cgroup
Cgroup Driver: systemd
2 安装kubeadm/kubelet/kubectl
在172.16.1.81、83节点上操作
kubeadm # 用来初始化集群的指令
kubelet # 在集群中的每个节点上用来启动Pod和容器等
kubectl # 用来与集群通信的命令行工具
2.1 添加阿里云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 clean all
# yum makecache
2.2 安装
由于版本更新频繁,这里指定版本号部署
# yum install -y kubelet-1.20.0 kubeadm-1.20.0
kubectl-1.20.0
# systemctl enable kubelet
3 部署Kubernetes Master
在172.16.1.81节点上操作
官方文档:
# https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/
# https://kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-init/
3.1 命令行方式引导
# kubeadm init \
--apiserver-advertise-address=172.16.1.81
\
--image-repository
registry.aliyuncs.com/google_containers \
--kubernetes-version
v1.20.0 \
--service-cidr=10.96.0.0/12
\
--pod-network-cidr=10.244.0.0/16
\
--ignore-preflight-errors=all
参数说明:
(1) --apiserver-advertise-address # 集群通告地址
(2)
--image-repository #
由于默认拉取镜像地址k8s.gcr.io国内无法访问,这里指定阿里云镜像仓库地址
(3)
--kubernetes-version #
K8s版本,与上面安装的一致
(4)
--service-cidr #
集群内部虚拟网络,Pod统一访问入口
(5)
--pod-network-cidr # Pod网络,,与下面部署的CNI网络组件yaml中保持一致
输出内容:
……(省略的日志)
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
Alternatively,
if you are the root user, you can run:
export
KUBECONFIG=/etc/kubernetes/admin.conf
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 172.16.1.81:6443 --token s53bbu.zzmnnbxtss6ydl70 \
--discovery-token-ca-cert-hash
sha256:cfb5e3e7711d91dd47007b6681230cf9dcc920d231c15b9dd3bf3ea1479f6571
# 初始化完成后,最后会输出一个join命令,先记住,下面用
3.2 使用配置文件方式引导
# cat > kubeadm-config.conf <<
EOF
apiVersion: kubeadm.k8s.io/v1beta2
kind:
ClusterConfiguration
kubernetesVersion:
v1.20.0
imageRepository:
registry.aliyuncs.com/google_containers
networking:
podSubnet:
10.244.0.0/16
serviceSubnet:
10.96.0.0/12
EOF
# kubeadm init --config kubeadm-config.conf --ignore-preflight-errors=all
3.3 拷贝kubectl使用的连接k8s认证文件到默认路径
# mkdir
-p $HOME/.kube
# sudo
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
# sudo
chown $(id -u):$(id -g) $HOME/.kube/config
查看工作节点:
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master1 NotReady control-plane,master 6m33s v1.20.0
注:由于网络插件还没有部署,还没有准备就绪
4 加入Kubernetes Node
在172.16.1.83节点上操作
官方文档: https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-join/
向集群添加新节点,执行在kubeadm init输出的kubeadm join命令
# kubeadm
join 172.16.1.81:6443 --token s53bbu.zzmnnbxtss6ydl70 \
--discovery-token-ca-cert-hash
sha256:cfb5e3e7711d91dd47007b6681230cf9dcc920d231c15b9dd3bf3ea1479f6571
注: 默认token有效期为24小时,当过期之后,该token就不可用了。这时就需要重新创建token,可以
直接使用命令快捷生成。kubeadm token create
--print-join-command
5 部署容器网络(CNI)
在172.16.1.81节点上操作
Calico是一个纯三层的数据中心网络方案,是目前Kubernetes主流的网络方案。
官方文档:
https://docs.projectcalico.org/getting-started/kubernetes/self-managed-onprem/onpremises
5.1下载YAML
# wget
https://docs.projectcalico.org/manifests/calico.yaml
注: calico镜像版本为v3.20.0
5.2 修改CALICO_IPV4POOL_CIDR
1 修改calico.yaml文件中定义Pod网络(CALICO_IPV4POOL_CIDR),与前面kubeadm init的
--pod-network-cidr指定的一样。
2 部署
# kubectl
apply -f calico.yaml
[root@k8s-master1 k8s]# kubectl get pods -A -o
wide
3 Calico Pod状态都为Running,节点准备就绪
[root@k8s-master1 k8s]# kubectl get
nodes
NAME STATUS ROLES AGE VERSION
k8s-master1 Ready control-plane,master 44m v1.20.0
k8s-node1 Ready <none> 41m v1.20.0
6 测试kubernetes集群
在172.16.1.81节点上操作
在Kubernetes集群中创建一个pod,验证是否正常运行
# kubectl create deployment nginx
--image=nginx
#
kubectl expose deployment nginx --name=nginx --port=80 --target-port=80
--type=NodePort
# kubectl get pod,svc
注: 访问地址:http://NodeIP:Port
7 部署 Dashboard
在172.16.1.81节点上操作
7.1 说明
Dashboard是官方提供的一个UI,可用于基本管理K8s资源。
1 官方文档
https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/
2 gitlab项目地址
https://github.com/kubernetes/dashboard
3 版本兼容
https://github.com/kubernetes/dashboard/releases/tag/v2.3.1
4 下载
# wget -O kubernetes-dashboard.yaml
https://raw.githubusercontent.com/kubernetes/dashboard/v2.3.1/aio/deploy/recommended.yaml
7.2 部署
1 修改kubernetes-dashboard.yaml配置
由于默认kubernetes-dashboard只能集群内部访问,因此修改Service为NodePort类型,暴露到k8s集群外部进行访问。
2 应用kubernetes-dashboard.yaml
[root@k8s-master1 ~]# kubectl apply -f
kubernetes-dashboard.yaml
#
查看pod状态
[root@k8s-master1
~]# kubectl get pod -n kubernetes-dashboard -o wide
注: kubernetes dashboard pod运行正常,访问地址: https://NodeIP:30001
3 创建访问dashboard的token
(1)
创建serviceaccount并赋权
1)
在kube-system命名空间中创建serviceaccount/dashboard-admin
#
kubectl create serviceaccount dashboard-admin -n kube-system
2)
绑定kube-system命名空间中serviceaccount/dashboard-admin到集群角色cluster-admin上
#
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin
\
--serviceaccount=kube-system:dashboard-admin
(2)
获取访问token
1) 获取kube-system命名空间中serviceaccount/dashboard-admin的secrets名称
#
kubectl describe serviceaccount dashboard-admin -n kube-system
2)
获取kube-system命名空间中secrets/dashboard-admin-token-f8fd5登录k8s集群的token
#
kubectl describe secrets dashboard-admin-token-f8fd5
-n kube-system > dashboard-admin.token
3)
补充: 一条命令获取token
# kubectl describe secrets -n kube-system $(kubectl
-n kube-system get secret | awk '/dashboard-admin/{print
$1}')
7.3 token登录Dashboard
https://kubernetes.io/docs/reference/access-authn-authz/authentication/
到此,kubeadm方式部署K8S1.20单Master集群就完成了,k8s集群全部pod状态如下所示。
8 切换容器引擎为Containerd
在172.16.1.81、83节点上操作
参考资料: https://kubernetes.io/zh/docs/setup/production-environment/container-runtimes/
(1) 容器运行时
1) 为了在 Pod 中运行容器,Kubernetes使用容器运行时(Container Runtime)。你需要在集群内
每个节点上安装一个容器运行时以使Pod可以运行在上面。
2) 默认情况下,Kubernetes使用容器运行时接口(Container Runtime Interface,CRI) 来与你所
选择的容器运行时交互。
3) 如果你不指定运行时,则kubeadm会自动尝试检测到系统上已经安装的运行时,方法是扫描
一组众所周知的域套接字。如果同时检测到 Docker 和 containerd,则优先选择 Docker。这
是必然的,因为附带了 containerd 并且两者都是可以检测到的,即使你仅安装了
Docker。
4) 如果检测到其他两个或多个运行时,kubeadm输出错误信息并退出。kubelet通过内置的
dockershim CRI实现与Docker集成。
(2) Cgroup驱动程序
1) 控制组用来约束分配给进程的资源
2) Linux系统发行版使用systemd作为其初始化系统时,初始化进程会生成并使用一个root控制组 (cgroup),并充当cgroup管理器。Systemd与cgroup集成紧密,并将为每个systemd单元分配一个
cgroup。你也可以配置容器运行时和kubelet使用cgroupfs。连同systemd一起使用cgroupfs意
味着将有两个不同的cgroup管理器。
3) 单个cgroup管理器将简化分配资源的视图,并且默认情况下将对可用资源和使用中的资源具有
更一致的视图。当有两个管理器共存于一个系统中时,最终将对这些资源产生两种视图。在此领域
人们已经报告过一些案例,某些节点配置让kubelet和docker使用cgroupfs,而节点上运行的其余
进程则使用systemd; 这类节点在资源压力下会变得不稳定。
4) 注意:
更改已加入集群的节点的cgroup驱动是一项敏感的操作。如果kubelet已经使用某cgroup驱动的
语义创建了pod,更改运行时以使用别的cgroup驱动, 当为现有Pods重新创建PodSandbox时会
产生错误。重启kubelet也可能无法解决此类问题。如果你有切实可行的自动化方案, 使用其他已更
新配置的节点来替换该节点, 或者使用自动化方案来重新安装。
8.1 安装和配置的先决条件
# 创建 .conf
文件以在启动时加载模块
cat
<<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
sudo
modprobe overlay
sudo
modprobe br_netfilter
#
设置必需的 sysctl 参数,这些参数在重新启动后仍然存在。
cat
<<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward =
1
net.bridge.bridge-nf-call-ip6tables
= 1
EOF
#
应用 sysctl 参数而无需重新启动
sudo sysctl –system
8.2 安装containerd(linux)
# 安装依赖包
yum
install -y yum-utils device-mapper-persistent-data lvm2
# 配置docker仓库源
yum-config-manager
\
--add-repo
\
https://download.docker.com/linux/centos/docker-ce.repo
# 更新为阿里云的docker仓库源
wget
-O /etc/yum.repos.d/docker-ce.repo
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装
yum
install -y containerd.io
mkdir
-p /etc/containerd
containerd
config default | sudo tee /etc/containerd/config.toml
systemctl
restart containerd
systemctl
enable containerd
8.3 修改配置文件
设置拉取Docker Hub镜像配置加速地址为阿里云镜像仓库地址
cgroups驱动设置为systemd
# 修改配置文件
vi
/etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image
= "registry.aliyuncs.com/google_containers/pause:3.2"
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup
= true
...
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint
= ["https://b1cx9cn7.mirror.aliyuncs.com"]
# 重新启动
systemctl restart containerd
8.4 配置kubelet使用containerd
# vim /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS=--container-runtime=remote
--container-runtime-endpoint=unix:///run/containerd/containerd.sock
--cgroup-driver=systemd
# systemctl restart kubelet
8.5 验证
[root@k8s-master1 ~]# kubectl get nodes -o
wide
注: 切回Docker引擎,就是把kubelet配置参数去掉即可。
8.6 管理容器工具
containerd提使用crictl工具检查和调试容器。
项目地址:https://github.com/kubernetes-sigs/cri-tools/
1 设置crictl连接containerd
# vi /etc/crictl.yaml
runtime-endpoint:
unix:///run/containerd/containerd.sock
image-endpoint:
unix:///run/containerd/containerd.sock
timeout:
10
debug:
false
[root@k8s-master1 ~]# crictl
images
2 docker与crictl命令对照表
镜像相关功能 | Docker | Containerd |
显示本地镜像列表 | docker images | crictl images |
下载镜像 | docker pull | crictl pull |
上传镜像 | docker push | 无,例如buildk |
删除本地镜像 | docker rmi | crictl rmi |
查看镜像详情 | docker inspect IMAGE-ID | crictl inspecti IMAGE-ID |
容器相关功能 | Docker | Containerd |
显示容器列表 | docker ps | crictl ps |
创建容器 | docker create | crictl create |
启动容器 | docker start | crictl start |
停止容器 | docker stop | crictl stop |
删除容器 | docker rm | crictl rm |
查看容器详情 | docker inspect | crictl inspect |
attach | docker attach | crictl attach |
exec | docker exec | crictl exec |
logs | docker logs | crictl logs |
stats | docker stats | crictl stats |
POD 相关功能 | Docker | Containerd |
显示 POD 列表 | 无 | crictl pods |
查看 POD 详情 | 无 | crictl inspectp |
运行 POD | 无 | crictl runp |
停止 POD | 无 | crictl stopp |
9 补充
9.1 k8s删除一直处于terminating状态的pod
# kubectl delete pod [pod name] --force --grace-period=0 -n [namespace]
9.2 无法访问k8s.gcr.io的解决办法
由于一些原因,在国内无法访问k8s.gcr.io上的镜像,在安装kubernetes时,很多官方镜像
又是都存在k8s.gcr.io上,在国内大都使用阿里云的镜像。
https://cloud.google.com/container-registry/使用阿里云镜像地址:
地址1:
registry.aliyuncs.com/google_containers
地址2:
registry.cn-hangzhou.aliyuncs.com/google_containers