k8s-01搭建

163 阅读8分钟

第1章 k8s系统架构

从系统架构来看,k8s分为2个节点
Master  控制节点  指挥官
Node    工作节点  干活的

image.png

1.Master节点组成

API Server :提供k8s API接口
主要处理Rest操作以及更新Etcd中的对象
是所有资源增删改查的唯一入口。

Scheduler:资源调度器
根据etcd里的节点资源状态决定将Pod绑定到哪个Node上

Controller Manager
负责保障pod的健康存在
资源对象的自动化控制中心,Kubernetes集群有很多控制器。

Etcd
这个是Kubernetes集群的数据库
所有持久化的状态信息存储在Etcd中

kubectl
kubectl是管理k8s集群的客户端⼯具,管理员通过kubectl命令对API Server进⾏操作
API Server 响应并返回对应的命令结果,从⽽达到对 Kubernetes 集群的管理

image.png

2.Node节点的组成

容器运⾏时(Container Runtime)

容器运⾏时是负责容器运⾏的软件。
默认情况下,Kubernetes 使⽤ 容器运⾏时接⼝(Container Runtime Interface,CRI) 来与你所选择的容器运⾏时交互

如果同时检测到 Docker 和 containerd,则优先选择 Docker。 这是必然的,因为 Docker 18.09 附带了containerd 并且两者都是可以检测到的, 即使你仅安装了 Docker。 如果检测到其他两个或多个运⾏时,kubeadm 输出错误信息并退出

kubelet 通过内置的 dockershim CRI 实现与 Docker 集成。
Docker Engine
负责节点容器的管理工作,最终创建出来的是一个Docker容器。

kubelet 
安装在Node上的代理服务,用来管理Pods以及容器/镜像/Volume等,实现对集群对节点的管理。

kube-proxy
安装在Node上的网络代理服务,提供网络代理以及负载均衡,实现与Service通讯。

image.png

第2章 k8s核心资源

从逻辑架构上看,k8s分为

Pod 
Controller 
Service   

1.POD

POD是k8s的最小单位
POD的IP地址是随机的,删除POD会改变IP
POD都有一个根容器
一个POD内可以由一个或多个容器组成
一个POD内的容器共享根容器的网络命名空间
一个POD的内的网络地址由根容器提供

image.png

创建Pod流程图:

image.png

⽂字说明:

创建Pod的清单 --> API Server
API Server --> etcd
etcd --> API Server
kube-scheduler --> API Server --> etcd
etcd --> API server --> kubelet --> Docker
kubelet --> API Server --> etcd

 管理员清单提交给了 APIServer
API Server 接收到请求后把资源清单信息存⼊到 etcd 数据库中
etcd 存好后更新状态给 API Server
API Server通过相应的接⼝更新事件
kube-scheduler 组件发现这个时候有⼀个 Pod 还没有绑定到节点上,就会对这个 Pod 进⾏⼀系列的调度,把它调度到⼀个最合适的节点上

然后把这个节点和 Pod 绑定到⼀起的信息告诉 API Server
API Server将调度消息更新到etcd⾥,etcd更新好后返回状态给API Server
节点上的 kubelet 组件这个时候 watch 到有⼀个 Pod 被分配过来了,就去把这个 Pod 的信息拉取下来,
然后根据描述通过容器运⾏时把容器创建出来,最后当然同样把 Pod 状态汇报给API Server 再写回到 etcd中去,这样就完成了⼀整个的创建流程。

容器运⾏状态:

Waiting(等待)
如果容器并不处在Running或Terminated状态之⼀,它就处在Waiting状态。 处于Waiting状态的容器仍在运⾏它完成启动所需要的操作:例如,从某个容器镜像 仓库拉取容器镜像,或者向容器应⽤数据等等。 当你使⽤kubectl 来查询包含 Waiting状态的容器的 Pod 时,你也会看到⼀个 Reason 字段,其中给出了容器处于等待状态的原因。

Running(运⾏中)
Running状态表明容器正在执⾏状态并且没有问题发⽣。
如果你使⽤ kubectl 来查询包含 Running 状态的容器的 Pod 时,你也会看到 关于容器进⼊Running状态的信息。

Terminated(已终⽌)
处于Terminated状态的容器已经开始执⾏并且或者正常结束或者因为某些原因失败。 如果你使⽤kubectl来查询包含Terminated状态的容器的 Pod 时,你会看到 容器进⼊此状态的原因、退出代码以及容器执⾏期间的起⽌时间。

2.Label

label标签是kubernetes中⾮常重要的⼀个属性,label标签就像身份证⼀样,可以⽤来识别k8s的对象。
我们在传统架构⾥不同组件之间查找都是通过IP地址,但是在k8s⾥,很多的匹配关系都是通过标签来查找的。

3.Namespace

Namespace(命令空间)是k8s⾥另⼀个⾮常重要的概念,Namespace通过将集群内部的资源对象划分为不同的。Namespace⾥,形成逻辑上的不同项⽬组或⽤户组。
常⻅的pod,service,Deployment等资源如果没有指定命令空间,则默认创建在名为default的默认命名空间。

4.Controller

用来管理POD,控制器的种类有很多
  - RC Replication Controller  控制POD有多个副本
  - RS ReplicaSet              RC控制的升级版
  - Deployment                 推荐使用,功能更强大,包含了RS控制器
  - DaemonSet                  保证所有的Node上有且只有一个Pod在运行
  - StatefulSet		       有状态的应用,为Pod提供唯一的标识,它可以保证部署和scale的顺序

5.Service

Service服务也是k8s的核⼼资源之⼀,Service定义了服务的⼊⼝地址,⽤来将后端的Pod服务暴露给外部⽤户访问。
我们知道Pod会随时被销毁和创建,⽽新创的Pod的IP地址并不是固定的,那么Service资源是如何找到后⾯不确定IP的Pod呢?

为了解决这个问题,k8s在PodIP之上⼜设计了⼀层IP,名为ClusterIP,这个ClusterIP在创建后就不会再变化,除⾮被删除重新创建。

通过这样的设计,我们只需要创建Cluster类型的Service资源,再通过标签和后端的Pod绑定在⼀起,这样只要访问ClusterIP就可以将请求转发到了后端的Pod,⽽且如果后端有多个Pod,ClusterIP还会将流量⾃动负载均衡到后⾯的Pod

通过ClusterIP我们可以访问对应的Pod,但是这个ClusterIP是⼀个虚拟IP,只能在k8s集群内部使⽤。外部⽤户是访问不到的,那么我们如何让外⾯的⽤户也可以访问到我们的服务呢?


我们的k8s运⾏在物理服务器上,那么必然会有物理⽹卡和真实的IP地址,也就是说所有k8s集群之外的节点想访问k8s集群内的某个节点,都必须通过物理⽹卡和IP

所以我们可以通过将物理⽹卡的IP地址的端⼝和Cluster做端⼝映射来实现外部流量对内部Pod的访问。
这种IP在k8s⾥称为NodeIP,暴露的端⼝称为NodePort。


#总结
NodeIP      对外提供用户访问
CluterIP    集群内部IP,可以动态感知后面的POD IP
POD IP      POD的IP

Service三种⽹络图:

Service和Pod和RS的关系:

image.png

第3章 k8s实验环境准备

1.配置信息

主机名	  	IP地址	   推荐配置     勉强配置
master    10.0.0.10    1C4G40G     1C2G		
node1     10.0.0.11    1C2G40G     1C1G
node2     10.0.0.12    1C2G40G     1C1G

----------------------------------------
初始化操作:
	干净环境
	配置主机名
	配置host解析
	关闭防火墙
	关闭SELinux
	配置时间同步
	更新好阿里源 
	确保网络通畅
	关闭SWAP分区

2.系统环境准备

配置主机名
主机名	   IP地址	     
master    10.0.0.10
node1     10.0.0.11
node2     10.0.0.12

3.配置host解析

cat >> /etc/hosts << EOF
10.0.0.10   master 
10.0.0.11   node1
10.0.0.12   node2
EOF

4.关闭防火墙

systemctl  stop  firewalld   NetworkManager 
systemctl  disable  firewalld   NetworkManager

5.关闭SELinux

setenforce 0
sed -i 's#SELINUX=disabled#SELINUX=disabled#g' /etc/selinux/config
getenforce

6.更新好阿里源

curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
sed -i '/aliyuncs/d' /etc/yum.repos.d/*.repo

7.确保网络通畅

ping -c 1 www.baidu.com
ping -c 1 master
ping -c 1 node1
ping -c 1 node2

8.配置时间同步

yum install chrony -y
systemctl start chronyd
systemctl enable chronyd
date

9.关闭SWAP分区

swapoff -a
sed -i '/swap/d' /etc/fstab
free -h

第4章安装部署kubeadm

k8s安装部署⽅式

k8s的安装⽅式有很多种,常⻅的安装⽅式主要有以下⼏种:
1.⼆进制安装 ⽣产推荐
2.kubeadm安装 学习和实验
3.⽹友写的ansible⼆进制安装 ⾮常⽜叉
4.第三⽅安装⼯具⽐如rancher
5.云服务的k8s ⽐如阿⾥云的ACK

这⾥我们应该把学习使⽤k8s作为⾸要任务,所以先选择安装最简单的kubeadm来部署⼀套k8s集群。

0.kubeadm介绍

kubeadm是google推出的⼀种部署k8s集群的套件,他将k8s的组件打包封装成了容器,然后通过kubeadm进⾏集群的初始化。
kubeadm的好处是安装部署⽅便,缺点是不容易看到每个组件的配置,出了问题不好排查。但是我们现在的重点是学习k8s的使⽤,所以这些优先选择简单的安装⽅式,最后会介绍⼆进制安装部署。

1.安装指定版本的docker

注意!所有机器都需要操作!!! 注意!所有机器都需要操作!!! 注意!所有机器都需要操作!!!

1.配置阿里源

cd /etc/yum.repos.d/
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

2.下载指定版本的docker

#yum list docker-ce --showduplicates
yum -y install docker-ce-19.03.15 docker-ce-cli-19.03.15

3.配置docker镜像加速

mkdir /etc/docker
cat > /etc/docker/daemon.json <<EOF
    {
      "registry-mirrors": ["https://ig2l319y.mirror.aliyuncs.com"],
      "exec-opts": ["native.cgroupdriver=systemd"]
    }
EOF

4.启动

systemctl enable docker && systemctl start docker

5.检查版本

docker -v

2.部署kubeadm和kubelet

注意!所有机器都需要操作!!! 注意!所有机器都需要操作!!! 注意!所有机器都需要操作!!!

1.设置k8s禁止使用swap

cat > /etc/sysconfig/kubelet<<EOF
KUBELET_CGROUP_ARGS="--cgroup-driver=systemd"
KUBELET_EXTRA_ARGS="--fail-swap-on=false"
EOF

2.设置内核参数

cat >  /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system

3.设置k8s国内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

4.安装kubeadm

#yum list kubeadm --showduplicates
yum install -y kubelet-1.19.3 kubeadm-1.19.3 kubectl-1.19.3 ipvsadm

5.设置kubelet开机启动

systemctl enable kubelet

6.加载IPVS模块

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
chmod +x /etc/sysconfig/modules/ipvs.modules
source /etc/sysconfig/modules/ipvs.modules
lsmod | grep -e ip_vs -e nf_conntrack_ipv

3.初始化集群部署Master

0.安装规划

节点规划

master  master节点  	API Server,controlle,scheduler,kube-proxy,kubelet,etcd
node1   node节点  	Dokcer kubelet kube-proxy 
node2   node节点  	Dokcer kubelet kube-proxy

IP规划

POD IP      10.2.0.0 
Cluster IP  10.1.0.0 
Node IP     10.0.0.0

1.初始化命令

注意!只在master节点运行!!!--主节点 注意!只在master节点运行!!!--主节点 注意!只在master节点运行!!!--主节点

官网地址:

https://v1-16.docs.kubernetes.io/zh/docs/reference/setup-tools/kubeadm/kubeadm-init/

初始化命令:

kubeadm init \
--apiserver-advertise-address=10.0.0.10 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.19.3 \
--service-cidr=10.1.0.0/16 \
--pod-network-cidr=10.2.0.0/16 \
--service-dns-domain=cluster.local \
--ignore-preflight-errors=Swap \
--ignore-preflight-errors=NumCPU

执行完成后会有输出,这是node节点加入k8s集群的命令

kubeadm join 10.0.0.10:6443 --token fsteby.4pz9czptzvxhzrg2 \
    --discovery-token-ca-cert-hash sha256:8466da60f808479cf39c78fbbfc7c80b397ac95ed23164253abe05a9c8c619b4 

2.为kubectl准备kubeconfig

  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节点信息

[root@master ~]# kubectl get nodes
NAME     STATUS     ROLES    AGE   VERSION
master   NotReady   master   2m37s   v1.19.3

4.支持命令补全

yum install bash-completion -y
source /usr/share/bash-completion/bash_completion
source <(kubectl completion bash)
kubectl completion bash >/etc/bash_completion.d/kubectl

5.设置kube-proxy使用ipvs模式

执行命令,然后将mode: ""修改为mode: "ipvs"然后保存退出

kubectl edit cm kube-proxy -n kube-system

重启kube-proxy

kubectl -n kube-system get pod|grep kube-proxy|awk '{print "kubectl -n kube-system delete pod "$1}'|bash

查看pod信息

kubectl get -n kube-system pod|grep "kube-proxy" 

检查日志,如果出现IPVS rr就表示成功

[root@master ~]kubectl -n kube-system logs -f kube-proxy-7cdbn 
I0225 08:03:57.736191       1 node.go:135] Successfully retrieved node IP: 10.0.0.10
I0225 08:03:57.736249       1 server_others.go:176] Using ipvs Proxier.
W0225 08:03:57.736841       1 proxier.go:420] IPVS scheduler not specified, use rr by default

检查IPVS规则

[root@master ~]ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.1.0.1:443 rr
  -> 10.0.0.10:6443               Masq    1      0          0         
TCP  10.1.0.10:53 rr
TCP  10.1.0.10:9153 rr
UDP  10.1.0.10:53 rr

4.部署网络插件

注意!只在master节点上安装部署!!! 注意!只在master节点上安装部署!!! 注意!只在master节点上安装部署!!

1.部署Flannel网络插件3

git clone --depth 1 https://github.com/coreos/flannel.git

2.修改资源配置清单

cd flannel/Documentation/
vim kube-flannel.yml
egrep -n "10.2.0.0|mirror|eth0" kube-flannel.yml
128:      "Network": "10.2.0.0/16",
189:        - --iface=eth0

3.应用资源配置清单

kubectl create -f kube-flannel.yml

4.检查pod运行状态,等一会应该全是running

[root@master ~]kubectl -n kube-system get pod
NAME                             READY   STATUS    RESTARTS   AGE
coredns-6d56c8448f-ckwhg         1/1     Running   0          6m43s
coredns-6d56c8448f-rvmdf         1/1     Running   0          6m43s
etcd-master                      1/1     Running   0          6m55s
kube-apiserver-master            1/1     Running   0          6m55s
kube-controller-manager-master   1/1     Running   0          6m55s
kube-flannel-ds-gzmxp            1/1     Running   0          15s
kube-flannel-ds-q4xtg            1/1     Running   0          2m42s
kube-flannel-ds-z6w27            1/1     Running   0          2m42s
kube-proxy-2zwxm                 1/1     Running   0          4m15s
kube-proxy-9q8n6                 1/1     Running   0          4m23s
kube-proxy-w295q                 1/1     Running   0          4m25s
kube-scheduler-master            1/1     Running   0          6m55s

5.部署Node节点

1.master节点输出增加节点的命令

kubeadm token create --print-join-command

2.node节点执行加入集群命令

kubeadm join 10.0.0.10:6443 --token uqf018.mia8v3i1zcai19sj  --discovery-token-ca-cert-hash sha256:e7d36e1fb53e59b12f0193f4733edb465d924321bcfc055f801cf1ea59d90aae 

3.在master节点上查看状态

kubectl get nodes

4.给节点打标签

[root@master ~]kubectl label nodes node1 node-role.kubernetes.io/node=
[root@master ~]kubectl label nodes node2 node-role.kubernetes.io/node=

5.再次查看节点状态

[root@master ~]# kubectl get nodes
NAME     STATUS   ROLES    AGE    VERSION
master   Ready    master   171m   v1.19.3
node1    Ready    node     27m    v1.19.3
node2    Ready    node     27m    v1.19.3