学习目标:
了解 Kubernetes 的起源和发展
掌握如何使用 kubeadm搭建 Kubernetes 集群
查看 Kubernetes 集群部署状态
4-1 Kubernetes的起源和发展
Kubernetes 的起源
- Kubernetes最初源于谷歌内部的Borg,Kubernetes 的最初目标是为应用的容器化编排部署提供一个最小化的平台,包含几个基本功能:
将应用水平扩容到多个集群
为扩容的实例提供负载均衡的策略
提供基本的健康检查和自愈能力
实现任务的统一调度
Kubernetes 的发展
2014年6月 谷歌云计算专家Eric Brewer在旧金山的发布会为这款新的开源工具揭牌。
2015年7月22日K8S迭代到 v 1.0并在OSCON大会上正式对外公布。
为了建立容器编排领域的标准和规范,Google、RedHat 等开源基础设施领域玩家们,在 2015 年共同牵头发起了名为 CNCF(Cloud Native Computing Foundation)的基金会。Kubernetes 成为 CNCF 最核心的项目。发起成员:AT&T, Box, Cisco, Cloud Foundry Foundation, CoreOS, Cycle Computing, Docker, eBay, Goldman Sachs, Google, Huawei, IBM, Intel, Joyent, Kismatic, Mesosphere, Red Hat, Switch SUPERNAP, Twitter, Univa, VMware and Weaveworks。
2018年,超过 1700 开发者成为 Kubernetes 项目社区贡献者,全球有 500 多场沙龙。国内出现大量基于 Kubernetes 的创业公司。
2020 年,Kubernetes 项目已经成为贡献者仅次于 Linux 项目的第二大开源项目。成为了业界容器编排的事实标准,各大厂商纷纷宣布支持 Kubernetes 作为容器编排的方案。
4-2 为什么需要 Kubernetes?
传统的容器编排痛点
容器技术虽然解决了应用和基础设施异构的问题,让应用可以做到一次构建,多次部署,但在复杂的微服务场景,单靠 Docker 技术还不够,它仍然有以下问题没有解决:
集成和编排微服务模块
提供按需自动扩容,缩容能力
故障自愈
集群内的通信
Kubernetes 能解决的问题
按需的垂直扩容,新的服务器(node)能够轻易的增加或删除
按需的水平扩容,容器实例能够轻松扩容,缩容
副本控制器,你不用担心副本的状态
服务发现和路由
自动部署和回滚,如果应用状态错误,可以实现自动回滚
什么时候使用 Kubernetes?
当你的应用是微服务架构
开发者需要快速部署自己的新功能到测试环境进行验证
降低硬件资源成本,提高使用率
什么时候不适合使用 Kubernetes
- 应用是轻量级的单体应用,没有高并发的需求
- 团队文化不适应变革
4-3 Kubernetes 的架构和核心概念
主控制节点组件
主控制节点组件对集群做出全局决策(比如调度),以及检测和响应集群事件(例如,当不满足部署的 replicas 字段时,启动新的 pod)。
主控制节点组件可以在集群中的任何节点上运行。 然而,为了简单起见,设置脚本通常会在同一个计算机上启动所有主控制节点组件,并且不会在此计算机上运行用户容器。
apiserver 主节点上负责提供 Kubernetes API 服务的组件;它是 Kubernetes 控制面的前端组件。
etcd etcd 是兼具一致性和高可用性的键值数据库,可以作为保存 Kubernetes 所有集群数据的后台数据库。
kube-scheduler 主节点上的组件,该组件监视那些新创建的未指定运行节点的 Pod,并选择节点让 Pod 在上面运行。 调度决策考虑的因素包括单个 Pod 和 Pod 集合的资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰和最后时限。
kube-controller-manager 在主节点上运行控制器的组件。 从逻辑上讲,每个控制器都是一个单独的进程,但是为了降低复杂性,它们都被编译到同一个可执行文件,并在一个进程中运行。这些控制器包括:
节点控制器(Node Controller): 负责在节点出现故障时进行通知和响应。
副本控制器(Replication Controller): 负责为系统中的每个副本控制器对象维护正确数量的 Pod。
终端控制器(Endpoints Controller): 填充终端(Endpoints)对象(即加入 Service 与 Pod)。
服务帐户和令牌控制器(Service Account & Token Controllers),为新的命名空间创建默认帐户和 API 访问令牌.
从节点组件
节点组件在每个节点上运行,维护运行的 Pod 并提供 Kubernetes 运行环境。
- kubelet 一个在集群中每个节点上运行的代理。它保证容器都运行在 Pod 中。
kubelet 接收一组通过各类机制提供给它的 PodSpecs,确保这些 PodSpecs 中描述的容器处于运行状态且健康。kubelet 不会管理不是由 Kubernetes 创建的容器。
- kube-proxy kube-proxy 是集群中每个节点上运行的网络代理,实现 Kubernetes Service 概念的一部分。 kube-proxy 维护节点上的网络规则。这些网络规则允许从集群内部或外部的网络会话与 Pod 进行网络通信。
- 容器运行时(Container Runtime) 容器运行环境是负责运行容器的软件。 Kubernetes 支持多个容器运行环境: Docker、 containerd、cri-o、 rktlet 以及任何实现 Kubernetes CRI (容器运行环境接口)。
插件(Addons)
DNS 尽管其他插件都并非严格意义上的必需组件,但几乎所有 Kubernetes 集群都应该有集群 DNS, 因为很多示例都需要 DNS 服务。
Web 界面(仪表盘) Dashboard 是 Kubernetes 集群的通用的、基于 Web 的用户界面。 它使用户可以管理集群中运行的应用程序以及集群本身并进行故障排除。
容器资源监控 容器资源监控 将关于容器的一些常见的时间序列度量值保存到一个集中的数据库中,并提供用于浏览这些数据的界面。
集群层面日志 集群层面日志 机制负责将容器的日志数据 保存到一个集中的日志存储中,该存储能够提供搜索和浏览接口。
4-4 Kubernetes 的部署方案介绍
部署目标
在所有节点上安装Docker和kubeadm
部署Kubernetes Master
部署容器网络插件
部署架构
环境准备
3台虚拟机CentOS7.x-86_x64
硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多
集群中所有机器之间网络互通
可以访问外网,需要拉取镜像
禁止swap分区
4-5 Virtualbox 虚拟机配置双网卡实现固定IP
Virtualbox安装 CentOS
配置虚机双网卡,实现固定 IP,且能访问外网 网卡 1: 仅主机host-only 网卡 2: 网络转换地址NAT 查看虚拟机网络,点击管理—>主机网络管理器,记住ip地址(192.168.99.1),并选择“手动配置网卡”。
重启虚拟机,此时在虚拟机 ping www.baidu.com 是返回成功的。
设置外部网络访问虚拟机 设置静态ip地址,编辑网络配置文件,编辑网络设置文件
vi /etc/sysconfig/network-scripts/ifcfg-enp0s3
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
#BOOTPROTO=dhcp
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=enp0s3
UUID=08012b4a-d6b1-41d9-a34d-e0f52a123e7a
DEVICE=enp0s3
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.99.101
- 重启网络
systemctl restart network
- 查看 enp0s3 网卡的 ip
[root@localhost Final]#ip addr |grep 192
inet 192.168.99.101/24 brd 192.168.99.255 scope global noprefixroute enp0s3
- 此时虚拟机既可以访问外网,也能够和宿主机( 192.168.31.178)进行通信
ping 192.168.31.178
PING 192.168.31.178 (192.168.31.178): 56 data bytes
64 bytes from 192.168.31.178: icmp_seq=0 ttl=64 time=0.060 ms
- 使用iTerm2 连接虚拟机
4-6 Master节点安装 kubeadm, kubelet and kubectl
- 配置 Master 和 work 节点的域名
vim /etc/hosts
192.168.56.101 master
192.168.56.102 node1
192.168.56.103 node2
- 设置域名解析服务器
vi /etc/resolv.conf
# Generated by NetworkManager
search lan
nameserver 114.114.114.114
剩余步骤可通过这个脚本执行:
- 下载阿里云的yum源:
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
- 安装基本软件包
yum install wget net‐tools ntp vim bash‐comp* ‐y
- 同步系统时间
ntpdate 0.asia.pool.ntp.org
- 将桥接的IPv4流量传递至iptables的链
[root@master ~]# modprobe br_netfilter
[root@master ~]# echo "1" >/proc/sys/net/bridge/bridge-nf-call-iptables
[root@master ~]# vi /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
- 关闭 防火墙
systemctl stop firewalld
systemctl disable firewalld
- 关闭 SeLinux
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
也可以修改 /etc/selinux/config
文件,如图片中所示
- 关闭 swap
swapoff -a
yes | cp /etc/fstab /etc/fstab_bak
cat /etc/fstab_bak |grep -v swap > /etc/fstab
也可以直接编辑 /etc/fstab
文件注释掉图片的内容
- free -m 发现swap全为0表示设置成功
- 设置主机名,管理节点设置主机名为master
[root@master ~]# hostnamectl set-hostname master
[root@master ~]# su ‐
- 配置Docker, K8S的阿里云yum源
[root@master ~]# 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=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
[root@master ~]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
[root@master ~]# yum repolist
- 安装并启动 docker
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum -y install docker-ce
mkdir /etc/docker
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://6yus5ux3.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
如果报错如下,则重新下载
wget -O /etc/yum.repos.d/CentOS-Base.repo [http://mirrors.aliyun.com/repo/Centos-7.repo](http://mirrors.aliyun.com/repo/Centos-7.repo)
如果还不行就使用以下脚本:
curl -fsSL get.docker.com -o get-docker.sh
bash get-docker.sh
- 编辑
/usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd
# Restart Docker
systemctl daemon-reload
systemctl enable docker
systemctl restart docker
此时查看 docker info
,可以看到默认 Cgroup Driver
为 systemd
- 卸载旧版本
yum remove -y kubelet kubeadm kubectl
- 安装kubelet、kubeadm、kubectl
yum install -y kubelet kubeadm kubectl
- 重启 docker,并启动 kubelet
systemctl enable kubelet && systemctl start kubelet
之后便可给Master节点打上快照,然后worker节点便可用这个快照进行构建。
4-8 初始化Master 节点
- 设置主机名,管理节点设置主机名为master
[root@master ~]# hostnamectl set-hostname master
[root@master ~]# su ‐
- 将桥接的IPv4流量传递到iptables的链
echo "1" >/proc/sys/net/bridge/bridge-nf-call-iptables
vi /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
剩余操作可通过以下脚本执行:注意修改版本和节点地址
- 初始化主节点
kubeadm init --kubernetes-version=1.23.1 \
--apiserver-advertise-address=192.168.56.101 \
--image-repository registry.aliyuncs.com/google_containers \
--service-cidr=10.1.0.0/16 \
--pod-network-cidr=10.244.0.0/16
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
- 初始化完成后记住图片中的内容(token),用于node节点的搭建
kubeadm join 192.168.56.101:6443 --token j0tuuf.p635m3gjlcn3d2w7 \
--discovery-token-ca-cert-hash sha256:b072d61cbfe86def68800a610e2f9eac45c34e83a55c6dab14691bf8a64cd4c1
- 检查节点信息
NAME STATUS ROLES AGE VERSION
master NotReady control-plane,master 6m26s v1.23.1
- 安装网络插件 Flannel
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml<
- 如果下载文件失败,或者无法从 quay.io/coreos 下载镜像,则可以使用代码库:
- 或者这个链接:[flannel.yml](https://www.yuque.com/docs/share/c3db0d5f-1c56-4831-9649-829870dc39bd?# 《Flannel.yml文件》)
kubectl apply -f kubeblog/docs/Chapter4/flannel.yaml
这个文件将flannel镜像上传到了dockerhub https://hub.docker.com/repository/docker/wangqingjiewa/flannel
- 查看kube-system状态
[root@master ~]# kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-6d8c4cb4d-r7q7n 1/1 Running 0 17m
coredns-6d8c4cb4d-sfqlb 1/1 Running 0 17m
etcd-master 1/1 Running 0 18m
kube-apiserver-master 1/1 Running 0 18m
kube-controller-manager-master 1/1 Running 0 18m
kube-flannel-ds-chd2n 1/1 Running 0 101s
kube-proxy-p42n2 1/1 Running 0 17m
kube-scheduler-master 1/1 Running 0 18m
- 查看master节点状态已经是ready
[root@master ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
master Ready control-plane,master 21m v1.23.1
- 查看是否成功创建flannel网络
ifconfig |grep flannel
报错处理
- 如果出现“node 'master' not found”错误
# 检查权限
chmod 777 /run/flannel/subnet.env
- 如果flannel pod启动失败,执行以下命令查看报错信息
kubectl describe pod kube-flannel-ds-xxx -n kube-system
- 如果是镜像拉取失败,可尝试修改
quay.io
的镜像路径。可以执行以下命令,并将结果保存至flannel.yml
,修改quay.io
的镜像路径,再执行delete和create操作
kubectl get pod kube-flannel-ds-xx -n kube-system -o yaml
kubectl delete -f flannel.yaml
kubectl create -f flannel.yaml
- 查看运行的Kubernetes组件
docker ps
如果出现“The connection to the server 192.168.56.101:6443 was refused - did you specify the right host or port?"错误
先执行: kubectl get po -n kube-system
,查看所有服务是否正常启动,如果某个服务启动失败,则执行
kubectl describe pod <pod name> -n kube-system
查看错误原因。
- 重置 kubeadm
kubeadm reset
4-9 安装配置 worker Node节点
-
初始虚拟机,Centos,配置双网卡
注意
clone snapshot
虚拟机时,选择Generate new MAC address
。 ssh 免密登录
设置 ip 地址为
192.168.99.102
配置域名
hostnamectl set-hostname node1
vi /etc/hosts
192.168.99.101 master
192.168.99.102 node1
192.168.99.103 node2
- 机器间互相免密,配置完成后需要重启机器
yum install openssh-server
ssh-keygen -t rsa
ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.56.101
reboot -f
如果安装有报错:没有安装deltarpm
就执行以下命令
yum provides '*/applydeltarpm'
yum -y install deltarpm
- 将 master 节点的
admin.conf
拷贝到 node1
scp /etc/kubernetes/admin.conf root@node1ip:/etc/kubernetes/
- 配置端口转发
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
echo 1 > /proc/sys/net/ipv4/ip_forward
- 配置 Kubeconfig 环境变量
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
source ~/.bash_profile
- 安装网络相关的工具
yum install net-tools
- 加入集群之前先清理拷贝过来的Master环境的网络
kubeadm reset
systemctl stop kubelet
systemctl stop docker
rm -rf /var/lib/cni/
rm -rf /var/lib/kubelet/*
rm -rf /etc/chi/
ifconfig cni0 down
ifconfig flannel.1 down
ifconfig docker0 down
ip link delete cni0
ip link delete flannel.1
systemctl start docker
systemctl start kubelet
- kubadm join 加入集群
systemctl enable kubelet.service
kubeadm join 192.168.99.101:6443 --token vrqf1w.dyg1wru7nz0ut9jz --discovery-token-ca-cert-hash sha256:1832d6d6c8386de5ecb1a7f512cfdef27a6d14ef901ffbe7d3c01d999d794f90
默认token的有效期为24小时,当过期之后,该token就不可用了。解决方法如下:
重新生成新的token,在master端执行
kubeadm token create --print-join-command
- 安装 flannel 网络插件
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
- 将master节点下面
/etc/cni/net.d/
下面的所有文件拷贝到node节点上
在node1节点上面创建目录: mkdir -p /etc/cni/net.d/
在master: scp /etc/cni/net.d/* root@nodeip:/etc/cni/net.d/
执行命令: kubectl get nodes 查看 node 节点处于ready状态
- 检查集群状态 稍等几分钟,在master节点输入命令检查集群状态.
kubectl get nodes
4-10 剖析kubeadm安装原理
Init 命令的工作流程
kubeadm init
命令通过执行下列步骤来启动一个 Kubernetes Control Plane
节点。
运行一系列的预检项来验证系统状态。一些检查项目仅仅触发警告, 其它的则会被视为错误并且退出
kubeadm
,除非问题得到解决或者用户指定了--ignore-preflight-errors=
参数。生成一个自签名的CA证书(或者使用现有的证书,如果提供的话)来为集群中的每一个组件建立身份标识。如果用户已经通过
--cert-dir
配置的证书目录(默认为/etc/kubernetes/pki
)提供了他们自己的 CA 证书以及/或者密钥,那么将会跳过这个步骤,正如文档使用自定义证书所述。将
kubeconfig
文件写入/etc/kubernetes/
目录,以便kubelet、控制器管理器和调度器用来连接到API 服务器,它们每一个都有自己的身份标识,同时生成一个名为admin.conf
的独立的kubeconfig
文件,用于管理操作。为 API服务器、控制器管理器和调度器生成静态Pod的清单文件。静态Pod的清单文件被写入到
/etc/kubernetes/manifests
目录;kubelet 会监视这个目录以便在系统启动的时候创建 Pod。一旦Control Plane
的 Pod 都运行起来,kubeadm init
的工作流程就继续往下执行。对
Control Plane
节点应用 labels 和 taints 标记以便不会在它上面运行其它的工作负载。生成令牌以便其它节点以后可以使用这个令牌向
Control Plane
节点注册自己。Kubeadm
会创建configmap
,提供添加节点所需要的信息。
查看创建的configmap
安装问题
- 用
docker ps -a
查看Kubernetes系统服务的状态 - Kubernetes集群启动问题,用journalctl查看日志
systemctl status kubelet
journalctl -xefu kubelet
journalctl -u kube-apiserver
- 用kubectl查看日志
注意:使用Kubelet describe
查看日志,一定要注意是否应包含命名空间
kubectl describe pod kubernetes-dashboard-xxx --namespace
kubectl logs -f pods/monitoring-influxdb-xxx -n kube-system
kubectl logs --tail 200 -f podname -n jenkins
- 执行
kubeadm join
异常问题
执行 kubeadm reset
,并且将 cni0,flannel1.1,docker0等网络规则删除,参考 Worker node 安装的章节。
- 镜像拉取不下来
修改 yaml 文件中的 image路径
4-11 安装Dashboard
- 下载Kubernetes Dashboard yaml 文件
https://www.yuque.com/insaneloafer/eqq96o/kssab0?inner=ltYwM
- 修改Service类型为NodePort
spec:
type: NodePort
ports:
- port: 443
targetPort: 8443
nodePort: 31111
selector:
k8s-app: kubernetes-dashboard
- 部署dashboard
kubectl create -f kubernetes-dashboard.yaml
kubectl apply -f kubernetes-dashboard.yaml
- 查看pod、svc状态
kubectl get pod,svc -n kubernetes-dashboard
- 非安全的浏览器访问
通过chrome浏览器访问https://192.168.99.102:31111,此时会返回“Your connection is not private”,无法跳转页面到Dashboard,这是由于 chrome 的安全设置,解决办法:鼠标点击当前页面,直接键盘输入thisisunsafe
,然后回车,即可进行页面跳转至 Dashboard登录页
- 获取登录 token
kubectl -n kube-system describe $(kubectl -n kube-system get secret -n kube-system -o name | grep namespace) | grep token
- 登录 Dashboard
在登录页面输入之前生成的 token,即可完成登录。