Kubernetes快速部署
在部署应用程序的方式上,主要经历了三个时代:
-
传统部署:互联网早期,会直接将应用程序部署在物理机上
优点:简单,不需要其它技术的参与
缺点:不能为应用程序定义资源使用边界,很难合理地分配计算资源,而且程序之间容易产生影响
-
虚拟化部署:可以在一台物理机上运行多个虚拟机,每个虚拟机都是独立的一个环境
优点:程序环境不会相互产生影响,提供了一定程度的安全性
缺点:增加了操作系统,浪费了部分资源
-
容器化部署:与虚拟化类似,但是共享了操作系统
优点:
可以保证每个容器拥有自己的文件系统、CPU、内存、进程空间等
运行应用程序所需要的资源都被容器包装,并和底层基础架构解耦
容器化的应用程序可以跨云服务商、跨Linux操作系统发行版进行部署
容器化部署方式给带来很多的便利,但是也会出现一些问题,比如说:
- 一个容器故障停机了,怎么样让另外一个容器立刻启动去替补停机的容器
- 当并发访问量变大的时候,怎么样做到横向扩展容器数量
这些容器管理的问题统称为容器编排问题,为了解决这些容器编排问题,就产生了一些容器编排的软件:
- Swarm:Docker自己的容器编排工具
- Mesos:Apache的一个资源统一管控的工具,需要和Marathon结合使用
- Kubernetes:Google开源的的容器编排工具
kubernetes简介
kubernetes,是一个全新的基于容器技术的分布式架构领先方案,是谷歌严格保密十几年的秘密武器----Borg系统的一个开源版本,于2014年9月发布第一个版本,2015年7月发布第一个正式版本。
kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。目的是实现资源管理的自动化,主要提供了如下的主要功能:
- 自我修复:一旦某一个容器崩溃,能够在1秒中左右迅速启动新的容器
- 弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整
- 服务发现:服务可以通过自动发现的形式找到它所依赖的服务
- 负载均衡:如果一个服务起动了多个容器,能够自动实现请求的负载均衡
- 版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本
- 存储编排:可以根据容器自身的需求自动创建存储卷
kubernetes组件
一个kubernetes集群主要是由控制节点(master)、**工作节点(node)**构成,每个节点上都会安装不同的组件。
master:集群的控制平面,负责集群的决策 ( 管理 )
ApiServer : 资源操作的唯一入口,接收用户输入的命令,提供认证、授权、API注册和发现等机制
Scheduler : 负责集群资源调度,按照预定的调度策略将Pod调度到相应的node节点上
ControllerManager : 负责维护集群的状态,比如程序部署安排、故障检测、自动扩展、滚动更新等
Etcd :负责存储集群中各种资源对象的信息
node:集群的数据平面,负责为容器提供运行环境 ( 干活 )
Kubelet : 负责维护容器的生命周期,即通过控制docker,来创建、更新、销毁容器
KubeProxy : 负责提供集群内部的服务发现和负载均衡
Docker : 负责节点上容器的各种操作
kubernetes概念
Master:集群控制节点,每个集群需要至少一个master节点负责集群的管控
Node:工作负载节点,由master分配容器到这些node工作节点上,然后node节点上的docker负责容器的运行
Pod:kubernetes的最小控制单元,容器都是运行在pod中的,一个pod中可以有1个或者多个容器
Controller:控制器,通过它来实现对pod的管理,比如启动pod、停止pod、伸缩pod的数量等等
Service:pod对外服务的统一入口,下面可以维护者同一类的多个pod
Label:标签,用于对pod进行分类,同一类pod会拥有相同的标签
NameSpace:命名空间,用来隔离pod的运行环境
安装部署kubernetes
安装要求
在开始之前,部署Kubernetes集群机器需要满足以下几个条件:
-至少3台机器,操作系统 CentOS7+
- 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘20GB或更多
- 集群中所有机器之间网络互通
- 可以访问外网,需要拉取镜像
- 禁止swap分区
准备工作:
主机 | 说明 | IP | 系统 |
---|---|---|---|
master.example.com | 控制节点 | 192.168.72.130 | CentOS-8 |
node1.example.com | 工作节点 | 192.168.72.131 | CentOS-8 |
node2.example.com | 工作节点 | 192.168.72.132 | CentOS-8 |
关闭防火墙、关闭seLinux、配置阿里源、关闭swap空间(在三台主机上都要操作)
[root@localhost ~]# systemctl disable --now firewalld.service
[root@localhost ~]# setenforce 0
[root@localhost ~]# sed -i 's/^SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
[root@localhost ~]# rm -rf /etc/yum.repos.d/*
[root@localhost ~]# curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo
[root@localhost ~]# sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo
[root@localhost ~]# yum clean all
18 files removed
[root@localhost ~]# yum makecache
删除swap空间
[root@localhost ~]# vim /etc/fstab
/dev/mapper/cs-root / xfs defaults 0 0
UUID=25b4542d-7c6a-4985-8731-adf87c5730e2 /boot xfs defaults 0 0
/dev/mapper/cs-swap none swap defaults 0 0
#/dev/mapper/cs-swap none swap defaults 0 0 #注释这一行
[root@localhost ~]# reboot 重启主机
给每台主机命名
[root@localhost ~]# hostnamectl set-hostname master.example.com
[root@localhost ~]# bash
[root@localhost ~]# hostnamectl set-hostname node1.example.com
[root@localhost ~]# bash
[root@localhost ~]# hostnamectl set-hostname node2.example.com
[root@localhost ~]# bash
添加hosts文件(三台主机都要做)
[root@master ~]# vim /etc/hosts
[root@master ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.72.130 master master.example.com #添加IP地址和主机名
192.168.72.131 node1 node1.example.com
192.168.72.132 node2 node2.example.com
[root@master ~]#
将桥接的IPv4流量传递到iptables的链(三台主机都要做)
[root@master ~]# touch /etc/sysctl.d/k8s.conf
[root@master ~]# 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
#生效
[root@master ~]# sysctl --system
时间同步
[root@master ~]# yum -y install chrony #安装chrony服务
[root@master ~]# systemctl enable --now chronyd
[root@master ~]# vi /etc/chrony.conf
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
pool time1.aliyun.com iburst #改为阿里云的时间同步
[root@master ~]# systemctl restart chronyd #重启服务
另外两台
[root@node1 ~]# yum -y install chrony #安装chrony服务
[root@node1 ~]# systemctl enable --now chronyd
[root@node1 ~]# vi /etc/chrony.conf
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
pool master iburst #工作节点去同步master节点的时间
[root@node2 ~]# systemctl restart chronyd
查看时间是否同步
[root@node2 ~]# date
Thu Nov 16 09:37:42 CST 2023
[root@master ~]# date
Thu Nov 16 09:37:13 CST 2023
[root@master ~]# chronyc sources #在master上查看
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^* 203.107.6.88 2 6 177 63 -994us[-1862us] +/- 31ms
[root@master ~]#
[root@node1 ~]# chronyc sources #在工作节点上查看
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^? master 0 8 0 - +0ns[ +0ns] +/- 0ns
[root@node1 ~]#
配置免密登录
[root@master ~]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:YL6eB/ucMDAImJUxnk+5BHwysKoanv2ltG8REUzePJ4 root@master.example.com
The key's randomart image is:
+---[RSA 3072]----+
|.o=o oo. |
|.==+...oo |
|= o++ o..+ |
|.. = + o. o |
|. . = . SE |
|. o.o |
|o .++. |
|o.o ..=*.. |
|.o ..+=++ |
+----[SHA256]-----+
[root@master ~]# ssh-copy-id master
[root@master ~]# ssh-copy-id node1
[root@master ~]# ssh-copy-id node2
#记得测试免密登录是否成功
所有节点安装Docker/kubeadm/kubelet
Kubernetes默认CRI(容器运行时)为Docker,因此先安装Docker。
安装Docker (三台主机都要做)
下载源
[root@master ~]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
yum安装docker
[root@master ~]# yum -y install docker-ce
启动docker并设置开机自启
[root@master ~]# systemctl enable --now docker
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /usr/lib/systemd/system/docker.service.
设置docker加速
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
EOF
[root@master ~]# systemctl restart docker
添加kubernetes阿里云YUM软件源(三台主机都要做)
配置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
[root@master ~]# yum makecache
安装kubeadm,kubelet和kubectl(三台主机都要做)
[root@master ~]# yum install -y kubelet kubeadm kubectl
[root@master ~]# systemctl enable kubelet #这里只能设置开机自启, 现在暂时不要启动
containerd配置(三台主机都要做)
为确保后面集群初始化及加入集群能够成功执行,需要配置containerd的配置文件/etc/containerd/config.toml,此操作需要在所有节点执行
#通过这行命令生成/etc/containerd/config.toml文件内容
[root@master ~]# containerd config default > /etc/containerd/config.toml
[root@master ~]# vi /etc/containerd/config.toml
...
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.6" #把这一行改为这样
...
[root@master ~]# systemctl restart containerd
[root@master ~]# systemctl enable containerd
由于默认拉取镜像地址k8s.gcr.io国内无法访问,所以这里指定阿里云镜像仓库地址。
部署Kubernetes Master(以下操作只在master主机执行)
# 用yum list all 查看一下要安装软件的版本信息,1.28.2
[root@master ~]# yum list all | grep kubelet
kubelet.x86_64 1.28.2-0 kubernetes
[root@master ~]# yum list all | grep kubectl
kubectl.x86_64 1.28.2-0 kubernetes
[root@master ~]# yum list all | grep kubeadm
kubeadm.x86_64 1.28.2-0
kubeadm init \
--apiserver-advertise-address=192.168.72.130 \ #这里是master主机的IP
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.28.2 \ #这里是安装kubernetes的版本,与前面的保持一致
--service-cidr=10.96.0.0/12 \ #默认网段不要改
--pod-network-cidr=10.244.0.0/16
#复制这里的
kubeadm init \
--apiserver-advertise-address=192.168.72.130 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.28.2 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16
#以下是运行结果最后部分的内容
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 192.168.72.130:6443 --token 4drnae.fghzjwampt0bcqng \
--discovery-token-ca-cert-hash sha256:858f81dc02c7b05d8df23f9c763c6ad9a516ee5a1f7b0a84cd8392314c0e4e38
[root@master ~]# vim init #把这部分内容写到一个文件里面,后面会用到
设置环境变量
[root@master ~]# echo 'export KUBECONFIG=/etc/kubernetes/admin.conf' > /etc/profile.d/k8s.sh
[root@master ~]# bash
[root@master ~]# echo $KUBECONFIG
/etc/kubernetes/admin.conf
部署flannel (Pod网络插件)
[root@master ~]# wget https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
配置falnnel
[root@master ~]# kubectl apply -f kube-flannel.yml
namespace/kube-flannel created
serviceaccount/flannel created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
[root@master ~]#
查看运行状态
[root@master ~]# kubectl get -f kube-flannel.yml
NAME STATUS AGE
namespace/kube-flannel Active 79s
NAME SECRETS AGE
serviceaccount/flannel 0 79s
NAME CREATED AT
clusterrole.rbac.authorization.k8s.io/flannel 2023-11-17T01:35:04Z
NAME ROLE AGE
clusterrolebinding.rbac.authorization.k8s.io/flannel ClusterRole/flannel 79s
NAME DATA AGE
configmap/kube-flannel-cfg 2 79s
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/kube-flannel-ds 1 1 1 1 1 <none> 79s
[root@master ~]#
将node1和node2加入到集群中(在node1和node2主机上操作)
#下面这条命令来自于刚刚保存的内容
[root@node1 ~]# kubeadm join 192.168.72.130:6443 --token 4drnae.fghzjwampt0bcqng \
> --discovery-token-ca-cert-hash sha256:858f81dc02c7b05d8df23f9c763c6ad9a516ee5a1f7b0a84cd8392314c0e4e38
在master节点上查看是否成功加入集群,刚加入可能会显示notready状态,是因为在加载flannel组件需要等一等,建议打开vpn会快一些。
[root@master ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master.example.com Ready control-plane 35m v1.28.2
node1.example.com Ready <none> 2m49s v1.28.2
node2 Ready <none> 62s v1.28.2
[root@master ~]#
[root@master ~]# kubectl get pods -n kube-flannel -o wide # 通过该命令可以查看到节点的详细信息
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-flannel-ds-522dw 1/1 Running 0 9m56s 192.168.72.131 node1.example.com <none> <none>
kube-flannel-ds-z9ggk 1/1 Running 0 8m9s 192.168.72.132 node2 <none> <none>
kube-flannel-ds-zpwbz 1/1 Running 0 20m 192.168.72.130 master.example.com <none> <none>
[root@master ~]#
测试Kubernetes集群
在Kubernetes集群中创建一个pod,验证是否正常运行
#由depolyment控制器来管理,创建一个名为nginx的pod,运行nginx镜像
[root@master ~]# kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
[root@master ~]#
查看pod
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-7854ff8877-hm57n 1/1 Running 0 111s
[root@master ~]#
[root@master ~]# kubectl get pods -o wide #加上-o wide可以看到IP
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-7854ff8877-hm57n 1/1 Running 0 2m12s 10.244.1.2 node1.example.com <none> <none>
[root@master ~]#
访问测试
#在集群内的节点中可以访问到
[root@master ~]# curl 10.244.1.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
.....
[root@node1 ~]# curl 10.244.1.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
......
[root@node2 ~]# curl 10.244.1.2
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
......
浏览器访问
由于我的真实主机不在集群内所有访问不到
暴露端口使公网可以访问
# 查看service
[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 78m
#查看kube-system命名空间中的所有Pod对象
[root@master ~]# kubectl get pods -n kube-system #创建的pod会自动在这里解析
NAME READY STATUS RESTARTS AGE
coredns-66f779496c-h45fh 1/1 Running 0 81m
coredns-66f779496c-sdblw 1/1 Running 0 81m
etcd-master.example.com 1/1 Running 0 81m
kube-apiserver-master.example.com 1/1 Running 0 81m
kube-controller-manager-master.example.com 1/1 Running 0 81m
kube-proxy-46wbj 1/1 Running 0 81m
kube-proxy-gcw4s 1/1 Running 0 49m
kube-proxy-nqkc4 1/1 Running 0 47m
kube-scheduler-master.example.com 1/1 Running 0 81m
[root@master ~]#
通过下面这行命令暴露名字叫nginx的deployment控制器的80端口、类型为NodePort,只有NodePort类型才可以在集群外访问、默认类型是
[root@master ~]# kubectl expose deployment nginx --port=80 --type=NodePort
service/nginx exposed
查看service,发现容器的80端口暴露为真机上的31403端口
[root@master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 107m
nginx NodePort 10.100.70.38 <none> 80:31403/TCP 21m
[root@master ~]#
用真机的IP加31403端口访问
通过添加环境变量使kubectl可以在node节点运行
首先查看保存的文件,里面有操作方法
[root@master ~]# cat init
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 #在普通用户的家目录中创建.kube目录
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config #在master主机中复制这个文件到node节点的.kube目录中
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 192.168.72.130:6443 --token kqrr5x.4q1mlp00mw6wenei \
--discovery-token-ca-cert-hash sha256:2b2030ec8f5c2c2faf2fc17412efc4a5d8b0819155a155eb5fd76cc3af34c2d7
[root@master ~]#
在node1、node2节点创建用户和.kube目录
[root@node1 ~]# useradd node
[root@node1 ~]# mkdir -p ~node/.kube #在node用户的家目录中创建.kube目录
在master节点中将/etc/kubernetes/admin.conf文件复制到node节点的.kube目录中
[root@master ~]# scp /etc/kubernetes/admin.conf node1:/home/node/.kube
admin.conf 100% 5650 3.6MB/s 00:00
[root@master ~]#
将拷贝过来的文件属主改为node
[root@node1 ~]# ls /home/node/.kube
admin.conf
[root@node1 ~]#
[root@node1 ~]# chown -R node.node ~node/.kube
[root@node1 ~]# ll -d /home/node/.kube/
drwxr-xr-x 2 node node 24 Nov 22 09:25 /home/node/.kube/
[root@node1 ~]# ll -d /home/node/.kube/admin.conf
-rw------- 1 node node 5650 Nov 22 09:25 /home/node/.kube/admin.conf
[root@node1 ~]#
node节点的.kube目录中
[root@master ~]# scp /etc/kubernetes/admin.conf node1:/home/node/.kube
admin.conf 100% 5650 3.6MB/s 00:00
[root@master ~]#
将拷贝过来的文件属主改为node
[root@node1 ~]# ls /home/node/.kube
admin.conf
[root@node1 ~]#
[root@node1 ~]# chown -R node.node ~node/.kube
[root@node1 ~]# ll -d /home/node/.kube/
drwxr-xr-x 2 node node 24 Nov 22 09:25 /home/node/.kube/
[root@node1 ~]# ll -d /home/node/.kube/admin.conf
-rw------- 1 node node 5650 Nov 22 09:25 /home/node/.kube/admin.conf
[root@node1 ~]#