一、k8s简介

1.1、步入容器部署时代

传统部署时代,程序直接部署在物理服务器之上,传统的方式带来了几个问题
1、物理资源的浪费,CPU与内存资源等计算资源;
2、对于不可靠的应用程序,因为程序的问题占用全部系统资源,导致服务器之上的其他程序无法工作;
3、扩容缩容操作需要新加物理设备,还需要割接,造成大量的金钱和人力的浪费
4、集成,部署操作相对于云时代过于复杂
容器部署时代:因为容器所具有的诸多优势,所以我们开始学习容器与容器编排工具

1.2、k8s的前世今生

容器时代,我们要使用容器部署集群应用,就离不开容器编排工具;而在业界,k8s占据了80%的市场份额,并且k8s的前身borg已经在谷歌稳定运行数十年,可以说,k8s是站在巨人的肩膀上。

1.3、k8s的功能

K8s可以自动装箱,自我修复,水平扩展,服务发现和负载均衡,自动发布和回滚
密钥和配置管理,存储编排,批处理执行。

二、k8s集群

舵手(K8s)修仙之旅第一篇 -- offline部署K8s_第1张图片

(架构图引自马哥文档)

2.1、k8s集群物理架构

Master :API server scheduler,controller-manager,etcd

一组master作为集群唯一入口,每一个node节点向集群贡献计算,存储等资源;客户端请求先发给master,master使用 scheduler(调度器)分析各node现有的可用资源,找一个最佳适配运行用户所请求容器的节点,调度该node负责实现用户请求;k8s可以自托管。
master上的API server是负责接收解析请求,scheduler负责分析各node上的计算和存储资源,并根据用户的请求进行两级调度,第一级预选有几个节点符合用户请求,第二级在符合用户请求的几个节点中优选出最佳节点来响应用户请求;
master上的组件controller-manager负责监控着每一个controller的健康状态,如果controller宕机,controller-manager会向API server请求重新创建controller
在一个集群中,master一般有三个,作成高可用,这样不管是API server scheduler,controller-manager中的哪一个宕机,都能保证服务的不间断稳定运行
每一个master的数据都是存在一个共享存储etcd上的,etcd是一个键值存储数据库,比较像是zookeeper,etcd中存储了整个集群的状态信息,所以etcd一般要作高可用,同时,etcd之间通信一般用https的方式,所以etcd内部通信需要一套CA和签署证书,etcd与API Server通信需要一套CA和签署证书,API Server与客户端通信需要一套CA和签署证书,API Server与kubelet、API Server与kube-proxy通信同样需要一套CA和签署证书。

Node:kubelet,docker(或其他容器引擎),kube-proxy,service,controller

kube-proxy用来管理service,当pod发生改变后,Label selector将消息报告给
API Server,API Server将这一事件通知给所有关联的组件知悉, kube-proxy知悉后改变本地node的iptables规则(service);service的改变需要依靠kube-proxy改变本地的iptables规则。
每一个node上都有一个kubelet,kubelet负责保证node始终处于健康运行状态,当node节点宕机时,controller会向API server发送请求,请求重新创建node;controller会在本地不断循环,周期性探测容器的健康状态,确保服务的不间断运行。

舵手(K8s)修仙之旅第一篇 -- offline部署K8s_第2张图片

2.2、k8s集群逻辑架构

逻辑架构:pod,label,label selector,namespace
pod:k8s上的最小调度单元,一个pod可以包含多个容器,这些容器共享同一个底层的namespace,pod更像是一个虚拟机,而pod上的各容器就像是运行在虚拟机之上的各个服务;同一个pod还可共享存储卷;一个pod中的容器一般以一个为主,其他为辅;
label: pod之上可以打上label,用label来识别pod,label是一个key=value形式的值
label selector:根据label来过滤符合条件的资源
namespace:namespace 可以将一个物理的 Cluster 逻辑上划分成多个虚拟 Cluster,每个 Cluster 就是一个 namespace。不同 namespace 里的资源是完全隔离的。

2.3、pod控制器

集群通过pod控制器管理pod
ReplicaSet(副本控制集):pod的多副本管理
Deployment:只能管理无状态应用,通过ReplicaSet管理pod的多副本
StatefulSet:管理有状态应用,保证pod的每个副本在整个生命周期名称不变
DaemonSet:在指定node上运行一个pod的场景
Job,ctonjob :用于任务结束后pod生命周期结束的场景

2.4、service

service为pod提供一个稳定的访问入口,做到了服务发现与服务注册功能,同时还有控制器的功能
客户端访问service,service将客户端的请求代理到后端的pod上,在后端pod改变时,service能动态发现新的pod,并将其加入。
service在1.10版本之前通过iptables deny规则实现,1.11版本后通过ipvs实现

2.5、附件

附件是为集群提供功能,附件的namespace在kube-system中
coreDNS:用于集群内名称解析
Web UI:集群管理UI
Container Resource Monitoring:资源检测
Cluster-level Logging:集群级日志记录

2.6、集群网络类型

CNI:第三方网络组件
flannel:网络配置,三层隧道叠加网络,简单
calico:网络配置,网络策略,支持BGP协议的路由直通模型,复杂
canel:flannel与calico结合,flannel提供网络配置,calico提供网络策略

三、offline部署准备

3.1、版本

系统:CentOS 7
Docker-ce:18.09
K8s:1.15.1

3.2、准备工作

使用flannel网络
节点网络:192.168.118.0/24
pod网络:10.244.0.0/16(flannel默认的)
service网络:10.96.0.0/12

master:192.168.118.220
Node1:192.168.118.221
Node2:192.168.118.222

各节点主机名称解析
配置DNS或/etc/hosts文件

192.168.118.220 k8s-master
192.168.118.221 k8s-node1
192.168.118.222 k8s-node2

各节点时间同步

uptime 192.168.118.220

关闭防火墙和selinux

systemctl stop firewalld.service
systemctl disable firewalld.service
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config 
reboot

各节点公钥免密

ssh-copy-id 192.168.118.221
ssh-copy-id 192.168.118.222

四、公网机rpm包及镜像准备

4.1、rpm包准备

下载地址: https://pkgs.org/download/
下载yum-utils以及其依赖包

4.2、配置k8s谷歌源下载k8s包

[root@k8s-master k8s]# cat > /etc/yum.repos.d/kubernetes.repo << EOF
> [kubernetes]
> name=Kubernetes
> baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
> enabled=1
> gpgcheck=1
> repo_gpgcheck=1
> gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
> EOF

4.3、安装yum-utils使用yumdownloader下载k8s包

yumdownloader --resolve kubelet kubeadm kubectl kubernetes-cni conntrack-tools libnetfil
ter_cthelper libnetfilter_cttimeout libnetfilter_queue socat

舵手(K8s)修仙之旅第一篇 -- offline部署K8s_第3张图片

4.4、下载docker-ce

当前k8s认证的docker-ce版本为18.09
下载地址: https://pkgs.org/download/

舵手(K8s)修仙之旅第一篇 -- offline部署K8s

4.5、安装docker

yum localinstall containerd.io-1.2.5-3.1.el7.x86_64.rpm docker-ce-18.09.8-3.el7.x86_6
4.rpm docker-ce-cli-18.09.8-3.el7.x86_64.rpm container-selinux-2.99-1.el7_6.noarch.rpm 

systemctl start docker

4.6、下载k8s镜像

docker pull k8s.gcr.io/kube-apiserver:v1.15.1
docker pull k8s.gcr.io/kube-controller-manager:v1.15.1
docker pull k8s.gcr.io/kube-scheduler:v1.15.1
docker pull k8s.gcr.io/kube-proxy:v1.15.1
docker pull k8s.gcr.io/coredns:1.3.1
docker pull k8s.gcr.io/pause:3.1
docker pull k8s.gcr.io/etcd:3.3.10

舵手(K8s)修仙之旅第一篇 -- offline部署K8s_第4张图片

4.7、保存镜像包

docker save k8s.gcr.io/kube-apiserver:v1.15.1 > ~/k8s-image/kube-apiserver.tar
docker save k8s.gcr.io/kube-controller-manager:v1.15.1 > ~/k8s-image/kube-controller-manager.tar
docker save k8s.gcr.io/kube-scheduler:v1.15.1 > ~/k8s-image/kube-scheduler.tar
docker save k8s.gcr.io/kube-proxy:v1.15.1 > ~/k8s-image/kube-proxy.tar
docker save k8s.gcr.io/coredns:1.3.1 > ~/k8s-image/coredns.tar
docker save k8s.gcr.io/pause:3.1 > ~/k8s-image/pause.tar
docker save k8s.gcr.io/etcd:3.3.10 > ~/k8s-image/etcd.tar

舵手(K8s)修仙之旅第一篇 -- offline部署K8s_第5张图片

4.8、准备fannel yaml文件

wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

4.9、集群准备rpm包

将下载的依赖包,以及docker-ce,k8s的rpm包,k8s的镜像包放在集群所有节点上

scp -r docker [email protected]:/root
scp -r k8s [email protected]:/root
scp -r k8s-image [email protected]:/root

五、offline部署kubernetes

5.1、根据k8s的要求修改内核参数(所有节点)

[root@k8s-master ~]# cat > /etc/sysctl.d/kubernetes.conf << EOF
> net.ipv4.ip_forword = 1
> net.bridge.bridge-nf-call-ip6tables = 1
> net.bridge.bridge-nf-call-iptables = 1
> EOF

5.2、重载内核配置(所有节点)

modprobe br_netfilter
sysctl --system

舵手(K8s)修仙之旅第一篇 -- offline部署K8s_第6张图片

5.3、配置集群初始化不检查swap(所有节点)

vim /etc/sysconfig/kubelet
KUBELET_EXTRA_ARGS="--fail-swap-on=false"

5.4、部署

安装4.5步骤

yum localinstall ./docker/*.rpm
systemctl start docker

安装4.3步骤下载的rpm包(所有节点)

yum localinstall ./k8s/*.rpm

K8s命令补全(所有节点)

source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

导入镜像(所有节点)

find . -name "*.tar" -exec docker image load -i {} \;

kubelet开机启动(所有节点)

systemctl enable kubelet

初始化master节点

kubeadm init  --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=Swap,NumCPU --apiserver-advertise-address=192.168.118.220 --kubernetes-version v1.15.1

舵手(K8s)修仙之旅第一篇 -- offline部署K8s
提示需要将docker的cgroup driver改为systemd

vim /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"]
}
systemctl  daemon-reload
systemctl restart docker
systemctl enable docker

舵手(K8s)修仙之旅第一篇 -- offline部署K8s
提示需要关闭swap以及cpu个数为2,我这里是虚拟机环境,所以跳过

重置初始化

kubeadm reset

继续初始化

kubeadm init  --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=Swap,NumCPU --apiserver-advertise-address=192.168.118.220 --kubernetes-version v1.15.1

舵手(K8s)修仙之旅第一篇 -- offline部署K8s_第7张图片

保存加入集群信息

kubeadm join 192.168.118.220:6443 --token ioiy2e.w5c73hie10whtrx0 \
    --discovery-token-ca-cert-hash sha256:0b309b3968902b155097c24912bdf7e695f9dba7523db6b7b854b40f0532f39a 

普通用户要使用k8s 需要执行下面操作

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

如果是root 可以直接执行

export KUBECONFIG=/etc/kubernetes/admin.conf

以上两个二选一即可,我这里用root

export KUBECONFIG=/etc/kubernetes/admin.conf

确认master各组件状态

[root@k8s-master docker]# kubectl get cs
NAME                 STATUS    MESSAGE             ERROR
scheduler            Healthy   ok                  
controller-manager   Healthy   ok                  
etcd-0               Healthy   {"health":"true"}   

将admin配置文件复制到所有node节点

scp /etc/kubernetes/admin.conf k8s-node1:/etc/kubernetes/
scp /etc/kubernetes/admin.conf k8s-node2:/etc/kubernetes/

配置环境变量

echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile

立即生效

source ~/.bash_profile

5.5、master添加flannel网络

kubectl apply -f kube-flannel.yml 

5.6、查看node以及pod状态

[root@k8s-master k8s]# kubectl get node
NAME         STATUS   ROLES    AGE     VERSION
k8s-master   Ready    master   7m42s   v1.15.1
[root@k8s-master k8s]# docker image ls
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
k8s.gcr.io/kube-scheduler            v1.15.1             b0b3c4c404da        6 days ago          81.1MB
k8s.gcr.io/kube-controller-manager   v1.15.1             d75082f1d121        6 days ago          159MB
k8s.gcr.io/kube-apiserver            v1.15.1             68c3eb07bfc3        6 days ago          207MB
k8s.gcr.io/kube-proxy                v1.15.1             89a062da739d        6 days ago          82.4MB
quay.io/coreos/flannel               v0.11.0-amd64       ff281650a721        5 months ago        52.6MB
k8s.gcr.io/coredns                   1.3.1               eb516548c180        6 months ago        40.3MB
k8s.gcr.io/etcd                      3.3.10              2c4adeb21b4f        7 months ago        258MB
k8s.gcr.io/pause                     3.1                 da86e6ba6ca1        19 months ago       742kB

5.7、node节点部署

将docker的cgroup driver改为systemd

vim /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"]
}
systemctl  daemon-reload
systemctl restart docker
systemctl enable docker

加入集群(跳过swap)

kubeadm join 192.168.118.220:6443 --token ioiy2e.w5c73hie10whtrx0     --discovery-token-ca-cert-hash sha256:0b309b3968902b155097c24912bdf7e695f9dba7523db6b7b854b40f0532f39a --ignore-preflight-errors=Swap

配置环境变量

echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile

立即生效

source ~/.bash_profile

5.8、查看node

[root@k8s-master ~]# kubectl get node
NAME         STATUS   ROLES    AGE    VERSION
k8s-master   Ready    master   29m    v1.15.1
k8s-node1    Ready       110s   v1.15.1
k8s-node2    Ready       107s   v1.15.1

六、node扩容

使用kubeadm方式部署k8s集群,要添加新的node加入集群,而默认token 24小时就会过期,所以超出24小时就要重新创建token
创建token

[root@k8s-master manifests]# kubeadm token create
3llex6.jb3l5afms93aexj5

获取ca证书sha256编码hash值

[root@k8s-master manifests]# openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* /
/'
0b309b3968902b155097c24912bdf7e695f9dba7523db6b7b854b40f0532f39a

加入集群新的命令

kubeadm join 192.168.118.220:6443 --token 3llex6.jb3l5afms93aexj5     --discovery-token-ca-cert-hash sha256:0b309b3968902b155097c24912bdf7e695f9dba7523db6b7b854b40f0532f39a --ignore-preflight-errors=Swap

七、kube-proxy使用ipvs负载均衡

7.1、k8s版本 在 v1.11版之后

7.2、下载并安装ipset以及ipvsadm包(所有节点)

yumdownloader --resolve ipset ipvsadm
yum localinstall ./ipvs/ip*
scp -r /root/ipvs k8s-node1:/root/
scp -r /root/ipvs k8s-node2:/root/
Node1:yum localinstall ./ipvs/ip*
Node2:yum localinstall ./ipvs/ip*

7.3、加载内核模块(所有节点)

modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4

7.4、检查加载的模块

lsmod | grep -e ipvs -e nf_conntrack_ipv4

7.5、更改configmap的mode配置为ipvs

kubectl edit configmap kube-proxy -n kube-system

舵手(K8s)修仙之旅第一篇 -- offline部署K8s_第8张图片

7.6、删除所有kube-proxy的pod

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

7.7、查看pod日志

kubectl get pod -n kube-system | grep kube-proxy
kubectl logs kube-proxy-7fsrg  -n kube-system

舵手(K8s)修仙之旅第一篇 -- offline部署K8s_第9张图片
出现Using ipvs Proxier即可

参考文章

https://www.jianshu.com/p/89f126b241db ipvs与iptables对比
https://ahmermansoor.blogspot.com/2019/04/install-kubernetes-k8s-offline-on-centos-7.html offline方式部署k8s
https://www.kubernetes.org.cn/5551.html 使用kubeadm安装Kubernetes 1.15
https://www.kubernetes.org.cn/doc-4 k8s中文文档
马哥文档