一、k8s简介
1.1、步入容器部署时代
传统部署时代,程序直接部署在物理服务器之上,传统的方式带来了几个问题
1、物理资源的浪费,CPU与内存资源等计算资源;
2、对于不可靠的应用程序,因为程序的问题占用全部系统资源,导致服务器之上的其他程序无法工作;
3、扩容缩容操作需要新加物理设备,还需要割接,造成大量的金钱和人力的浪费
4、集成,部署操作相对于云时代过于复杂
容器部署时代:因为容器所具有的诸多优势,所以我们开始学习容器与容器编排工具
1.2、k8s的前世今生
容器时代,我们要使用容器部署集群应用,就离不开容器编排工具;而在业界,k8s占据了80%的市场份额,并且k8s的前身borg已经在谷歌稳定运行数十年,可以说,k8s是站在巨人的肩膀上。
1.3、k8s的功能
K8s可以自动装箱,自我修复,水平扩展,服务发现和负载均衡,自动发布和回滚
密钥和配置管理,存储编排,批处理执行。
二、k8s集群
(架构图引自马哥文档)
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会在本地不断循环,周期性探测容器的健康状态,确保服务的不间断运行。
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
4.4、下载docker-ce
当前k8s认证的docker-ce版本为18.09
下载地址: https://pkgs.org/download/
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
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
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 root@192.168.118.221:/root
scp -r k8s root@192.168.118.221:/root
scp -r k8s-image root@192.168.118.221:/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
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
提示需要将docker的cgroup driver改为systemd
vim /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
systemctl daemon-reload
systemctl restart docker
systemctl enable docker
提示需要关闭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
保存加入集群信息
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 <none> 110s v1.15.1
k8s-node2 Ready <none> 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
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
出现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中文文档
马哥文档