1. Kubernetes介绍
下载网址:https://github.com/kubernetes/kubernetes/releases
1.1 Kubernetes的概述
- 容器编排技术:
容器编排系统可以对多个docker主机进行统一的管理和调度,协调容器化应用程序的部署、伸缩、发现和管理。主要的容器编排系统如下- Docker Swarm: Docker官方提供的容器编排系统,用于将一组docker主机组建成一个集群,提供容器化集群管理系统
- Mesos: Apache开源的分布式资源管理框架,支持docker容器管理,可用于构建大规模容器集群
- Kubernetes: Google开源的容器编排系统,由内部运行的Borg集群管理系统演变而来,凝聚了生产环境中大规模容器运维的经验。
- Kubernetes旨在简化容器化应用程序的部署和管理,它提供了许多功能,例如自动上线和回滚、容器自我修复、水平扩展、存储编排、配置管理等,以满足应用程序容器化管理多方面的需求。
- 不必再关心传统系统架构中那些和业务没有多大关系的底层代码或功能模块。
- 不必再费心于负载均衡器的选型和部署实施问题。
- 不必再考虑引入或自己开发一个复杂的服务治理框架。
- 不必再头疼于服务监控和故障处理模块的开发。
- 由于Kubernetes提供了强大的自动化机制,所以系统后期的运维难度和运维成本大幅度降低。
- Kubernetes是一个开放的开发平台。
- 与J2EE不同,它不局限于任何一种语言,没有限定任何编程接口,所以不论是用Java、Go、C++还是用Python编写的服务,都可以被映射为Kubernetes的Service(服务),并通过标准的TCP通信协议进行交互。
- Kubernetes平台对现有的编程语言、编程框架、中间件没有任何侵入性,因此现有的系统也很容易改造升级并迁移到Kubernetes平台上。
- Kubernetes是一个完备的分布式系统支撑平台。
- Kubernetes具有完备的集群管理能力,包括多层次的安全防护和准入机制、多租户应用支撑能力、透明的服务注册和服务发现机制、内建的智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、可扩展的资源自动调度机制,以及多粒度的资源配额管理能力。
- Kubernetes提供了完善的管理工具,这些工具涵盖了包括开发、部署测试、运维监控在内的各个环节。
- 因此,Kubernetes是一个全新的基于容器技术的分布式架构解决方案,并且是一个一站式的完备的分布式系统开发和支撑平台。
1.2 Kubernetes的基本知识
1.2.1 架构
Kubernetes(简称K8s)是一个开源的容器编排工具,专为自动化容器化应用程序的部署、扩展和管理而设计。以下是Kubernetes架构图的详细说明:
kubernetes 结构中,master 节点运行着各种各样的组件,master 节点负责控制整个集群,当然在很大的集群中也可以有多个 master 节点;而node节点负责运行我们的容器应用。这种结构一般称为 master-slave 结构。工作节点挂了没关系,master 节点会将故障节点上的业务自动在另一个节点上部署。
下面是kubernetes一些概念:
1.2.2 组件
Master组件
Master组件相当于集群的大脑,控制平面:
-
所有集群的控制命令都传递给Master组件并在其上执行
-
每个Kubernetes集群至少有一套Master组件(当前默认∶一个)
-
每套master组件包括三个核心组件(apiserver,scheduler和controller-manager)以及集群数据配置中心etcd
-
API Server组件:
- 集群控制的唯一入口,是提供Kubernetes集群控制RESTful API的核心组件
- 集群内各个组件之间数据交互和通信的中枢
- 提供集群控制的安全机制(身份认证、授权以及admission control)
-
Scheduler组件:
- 通过API Server的Watch接口监听新建Pod副本信息,并通过调度算法为该Pod选择一个最合适的Node
- 支持自定义调度算法provider
- 默认调度算法内置预选策略和优选策略,决策考量资源需求、服务质量、软硬件约束、亲缘性、数据局部性等指标参数
-
ControllerManager组件:
- 集群内各种资源controller的核心管理者
- 针对每一种具体的资源,都有相应的Controller
- 保证其下管理的每个Controller所对应的资源始终处于“期望状态”。
-
Etcd组件:
- Kubernetes集群的主数据库,存储着所有资源对象以及状态
- 默认与Master组件部署在一个Node上
- Etcd的数据变更都是通过API Server进行
Node组件
Node : Kubernetes集群中真正的工作负载节点:
-
Kubernetes集群由多个Node共同承担工作负载,Pod被分配到某个具体的Node上执行
-
kubernetes通过node controller对node资源进行管理。支持动态在集群中添加或删除Node
-
每个集群Node上都会部署Kubelet和Kube-proxy两个组件
-
Kubelet组件:
- 位于集群中每个Node上的非容器形式的服务进程组件,Master和node之间的桥梁
- 处理Master下发到本Node上的Pod创建、启停等管理任务;向APIServer注册Node信息
- 监控本Node上容器和节点资源情况,并定期向Master汇报节点资源占用情况
-
Kube-proxy组件:
- kube-proxy:运行在每个Node上
- Service抽象概念的实现,将到Service的请求按策略(负载均衡)算法分发到后端Pod(Endpoint)上
- 默认使用iptables mode实现
- 支持nodeport模式,实现从外部访问集群内的service
1.3 核心资源
2. Kubernetes安装部署
Kubernetes从1.4版本开始引入了命令行工具kubeadm,致力于简化集群的安装过程,并解决Kubernetes集群的高可用问题。
2.1 环境准备.
2.1.1 服务器信息
- Kubernetes集群节点信息:
集群角色 | hostname | OS | IP |
---|---|---|---|
Master | centos7-master | Centos7.9.2009_x64 | 192.168.0.113 |
Node | centos7-node | Centos7.9.2009_x64 | 192.168.0.114 |
- 集群节点运行的组件:
在图中环境里,选择Docker作为Kubernetes的运行容器,因此我们在部署Kubernetes组件时,还需要部署上Docker相关服务,并且要保证Docker容器可以访问网络下载容器镜像,容器之间的网络也必须互通。
2.1.2 系统初始化配置
在搭建Kubernetes集群之前,需要对操作系统进行一系列配置,以满足环境要求:
- 设置机器主机名
# 在192.168.0.113上执行如下:
[root@centos7-master ~]# hostnamectl set-hostname centos7-master && bash
# 在192.168.0.114上执行如下:
[root@centos7-node ~]# hostnamectl set-hostname centos7-node && bash
- 清空Iptables默认规则
Iptables默认会生成一些规则。Iptables配置不正确,会影响节点之间的通信,所以我们这里清空Iptables默认规则
[root@centos7-master ~]# iptables -F
- 关闭SELinux
禁用SELinux,让容器可以读取主机文件系统:
# 查看selinux的状态
[root@centos7-master ~]# getenforce
# 临时有效
[root@centos7-master ~]# setenforce 0
#永久有效, 改系统文件/etc/sysconfig/selinux,然后重启机器
[root@centos7-master ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
- 关闭Swap交换分区
Swap是一种虚拟内存技术,如果机器内存不够,会使用swap分区,但是swap分区的性能较低,k8s设计的时候为了能提升性能,默认是不允许使用交换分区的。Kubeadm初始化的时候会检测swap是否关闭,如果没关闭,那就初始化失败。如果不想要关闭交换分区,初始化k8s的时候可以指定--ignore-preflight-errors=Swap来解决。
#查看swap状态
[root@centos7-master ~]# free -h
#关闭swap,临时有效
[root@centos7-master ~]# swapoff -a
#注释掉swap,重启机器,永久有效
[root@centos7-master ~]# vim /etc/fstab
#/dev/mapper/centos-swap swap swap defaults 0 0
- 关闭firewalld防火墙
在CentOS Linux 7系统中默认启动了防火墙服务(firewalld),而Kubernetes的Master与工作Node之间会有大量的网络通信,安全的做法是在防火墙上配置各组件需要相互通信的端口号。
当然在安全的内部网络环境中可以关闭防火墙服务,我们在这里是直接关闭防火墙服务:
#查看防护墙状态
[root@centos7-master ~]# systemctl status firewalld.service
#关闭防火墙
[root@centos7-master ~]# systemctl stop firewalld.service
[root@centos7-master ~]# systemctl disable firewalld.service
- 配置内核参数
某些Kubernetes网络插件可能使用网络桥接(Bridge),为了确保网络桥接的数据包经过Iptables处理,需要启动相关的内核参数:
# 创建k8s.conf文件
[root@centos7-master ~]# touch /etc/sysctl.d/k8s.conf
# 修改内核参数
[root@centos7-master ~]# cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# 使修改的参数生效
sysctl -p /etc/sysctl.d/k8s.conf
- 配置时间同步
# 安装ntpdate
[root@centos7-master ~]# yum install ntpdate -y
# 同步时间
[root@centos7-master ~]# ntpdate ntp1.aliyun.com
2.2 安装Docker(所有节点,包含Master和Node)
因为Docker软件包未被包含在系统默认软件源中,需要额外配置Yum软件源,这里我们选择配置阿里云Yum软件源
阿里云Docker CE镜像推荐安装方法
# step1: 安装必要的一些系统工具
[root@centos7-master ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
# step2: 添加软件源信息
[root@centos7-master ~]# yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# step3
[root@centos7-master ~]# sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
# step4: 更新并安装Docker-CE
[root@centos7-master ~]# yum makecache fast
[root@centos7-master ~]# yum -y install docker-ce
# step5: 开启Docker服务并设置开机启动
[root@centos7-master ~]# systemctl start docker
[root@centos7-master ~]# systemctl enable docker
验证安装是否成功
2.3 安装cri-docker(所有节点,包含Master和Node)
从Kubernetes 1.24版本开始,使用Docker作为容器运行时,需要安装cri-docker. 文件可以github下载(https://github.com/Mirantis/cri-dockerd/releases),这里使用下载的版本是cri-dockerd-0.3.2-3.el7.x86_64.rpm。
[root@centos7-master ~]# yum -ivh cri-dockerd-0.3.2-3.el7.x86_64.rpm
安装完成后,修改Systemd服务文件,将依赖的Pause镜像指定为阿里云镜像地址
[root@centos7-master ~]# vim /usr/lib/systemd/system/cri-docker.service
...
ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint fd:// --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9
...
开启cri-docker服务并设置开机启动
[root@centos7-master ~]# systemctl start cri-docker
[root@centos7-master ~]# systemctl enable cri-docker
2.4 安装kubeadm、kubelet和kubectl(所有节点,包含Master和Node)
因为Kubernetes软件包未被包含在系统默认软件源中,需要额外配置Yum软件源,这里我们选择配置阿里云Yum软件源
阿里云镜像推荐安装方法
# 配置阿里云Yum Kubernetes软件源
[root@centos7-master ~]# vim /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/repodata/repomd.xml.key
# 安装kubelet、kubeadm和kubectl
[root@centos7-master ~]# yum install -y kubelet kubeadm kubectl
[root@centos7-master ~]# systemctl enable kubelet
[root@centos7-master ~]# systemctl start kubelet
2.5 部署Master节点
2.5.1 拉取master需要相关镜像
默认拉取的是k8s.gcr.io上的镜像(国内不能访问该网站)
#列出所需的镜像列表
[root@centos7-master ~]# kubeadm config images list
registry.k8s.io/kube-apiserver:v1.28.14
registry.k8s.io/kube-controller-manager:v1.28.14
registry.k8s.io/kube-scheduler:v1.28.14
registry.k8s.io/kube-proxy:v1.28.14
registry.k8s.io/pause:3.9
registry.k8s.io/etcd:3.5.15-0
registry.k8s.io/coredns/coredns:v1.10.1
#拉取镜像到本地
[root@centos7-master ~]# kubeadm config images pull #因拉取超时而失败
- 使用aliyun的镜像仓库获取镜像
拉取镜像
[root@centos7-master ~]# kubeadm config images pull --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers
# 擦看拉取完成的镜像
[root@centos7-master ~]# docker images
REPOSITORY
registry.cn-hangzhou.aliyuncs.com/google_containers/etcd 3.5.15-0 2e96e5913fc0 8 weeks ago 148MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver v1.28.0 bb5e0dde9054 13 months ago 126MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler v1.28.0 f6f496300a2a 13 months ago 60.1MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager v1.28.0 4be79c38a4ba 13 months ago 122MB
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy v1.28.0 ea1030da44aa 13 months ago 73.1MB
registry.cn-hangzhou.aliyuncs.com/google_containers/coredns v1.10.1 ead0a4a53df8 19 months ago 53.6MB
registry.cn-hangzhou.aliyuncs.com/google_containers/pause 3.9 e6f181688397 23 months ago 744kB
2.5.2 初始化master节点
- kubeadm的安装过程不涉及网络插件(CNI)的初始化,因此kubeadm初步安装完成的集群不具备网络功能,任何Pod包括自带的CoreDNS都无法正常工作。
- 网络插件的安装往往对kubeadm init命令的参数有一定的要求。例如,安装Flannel或Calico插件时需要指定--pod-network-cidr的值。
kubeadm init \
--apiserver-advertise-address=192.168.0.113 \
--image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers \
--kubernetes-version=v1.28.0 \
--pod-network-cidr=10.10.0.0/16 \
--service-cidr=10.20.0.0/16 \
--cri-socket=unix:///var/run/cri-dockerd.sock
- --apiserver-advertise-address: 指定API Server监听的IP地址。如果没有设置,则将使用默认的网络接口
- --image-repository:指定国内的阿里云镜像仓库
- --kubernetes-version:指定kubernetes的版本号
- --pod-network-cidr:Pod可以用的网络
- --service-cidr:Service可以用的网络
- --cri-socket: 指定kubelet连接容器运行时的UNIX套接字文件
执行命令后控制台会输出初始化成功的信息
2.5.3 初始化后的操作
- 让用户可以使用kubectl
#如果是普通用户执行以下命令
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
#永久有效
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /etc/profile
source /etc/profile
- 保留最后的输出:这是node节点加入集群的凭证,在node上用root用户执行下面的命令就可以加入该集群。
kubeadm join 192.168.0.113:6443 --token lqvb5o.i9898ysod4jc4339 \
--discovery-token-ca-cert-hash sha256:ff6545eeb935c4a3d6df6fe7357420faa229cd86824ab1b03fc28668c6eef84b
master节点初始化结束后可以执行kubectl命令来查看节点情况
2.6 部署Node节点
在node节点上执行上面保存的kubeadm join命令,并添加"--cri-socket"参数
kubeadm join 192.168.0.113:6443 --token lqvb5o.i9898ysod4jc4339 \
--discovery-token-ca-cert-hash sha256:ff6545eeb935c4a3d6df6fe7357420faa229cd86824ab1b03fc28668c6eef84b \
--cri-socket=unix:///var/run/cri-dockerd.sock
可以看到下面的输出
node节点添加成功后可以在master节点上执行"kubectl get nodes"命令来查看节点情况,结果如下
可以看到node节点已经被成功添加到集群中。kubedam默认根据主机名来设置节点名称,也可以添加"--node-name"参数自定义节点名称。
2.7 部署网络插件
在上面结果中,节点状态显示为"NotReady", 表示该节点尚未准备就绪,这是由于kebulet服务未发现网络插件导致的,kubelet日志中也对此进行了说明("network plugin is no ready")
Kubernetes网络插件主要用于实现集群内部Pod通信,负责配置和管理Pod的网络,常见的网络插件包括Calico、Flannel、Cilium等,这里选择使用Calico作为Kubernetes的网络插件,安装Calico网络插件:
[root@centos7-master ~]# wget https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/tigera-operator.yaml
[root@centos7-master ~]# kubectl create -f tigera-operator.yaml
[root@centos7-master ~]# wget https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/custom-resources.yaml
[root@centos7-master ~]# vim custom-resources.yaml
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
# Configures Calico networking.
calicoNetwork:
# Note: The ipPools section cannot be modified post-install.
ipPools:
- blockSize: 26
cidr: 10.10.0.0/16 # 修改此值,与"kubeadm init"命令中指定的Pod网络CIDR地址范围保持一致
encapsulation: VXLANCrossSubnet
natOutgoing: Enabled
nodeSelector: all()
...
等待片刻,查看Pod对象
注意
- ImagePullBackoff / Pending
如果 kubectl get pod -n kube-system -o wide 的输出结果中出现 ImagePullBackoff 或者长时间处于 Pending 的情况,可以按照这个办法查看镜像的下载进度
命令:kubectl get pods -n calico-system -o wide
结果:
碰到这个问题时,可按如下步骤解决: - 确定问题 Pod 所在节点,以calico-system名称空间下的Pod calico-node-kv66f为例:
[root@centos7-master ~]# kubectl get pods calico-node-kv66f -n calico-system -o wide
从这个就结果中,我们得知,该Pod被调度到了 master 节点
- 确定Pod所使用的容器镜像:
[root@centos7-master ~]# kubectl get pods calico-node-kv66f -n calico-system -o yaml | grep image:
从这个结果中,我们得知,该 Pod 使用到了容器镜像docker.io/calico/node:v3.26.0、docker.io/calico/pod2daemon-flexvol:v3.26.0、docker.io/calico/cni:v3.26.0
- 在Pod所在节点执行手动执行docker pull指令:
[root@centos7-master ~]# docker pull docker.io/calico/node:v3.26.0
[root@centos7-master ~]# docker pull docker.io/calico/pod2daemon-flexvol:v3.26.0
[root@centos7-master ~]# docker pull docker.io/calico/cni:v3.26.0
如果镜像标签没有问题,docker 指令将显示该镜像的下载过程,耐心等待即可。
所有Pod状态均显示为"Running",说明Calico安装成功,再通过"kubectl get nodes"命令查看节点,状态转为"Ready", 表示节点准备就绪。
注意:Kubernetes为了安全性,kubeadm join命令的token的有效时间为24个小时,过期后不可再使用,24小时内,您可以使用此token初始化任意数量的worker节点。如果超出时间还要加入新的节点,可以使用命令"kubeadm token create --print-join-command"创建新的token,以添加新的node节点。
2.8 部署Dashboard
Dashboard是官方开发的一个web管理系统,通过他,你可以管理集群资源、查看应用概览、查看容器日志和访问容器等操作。
- 下载Dashboard资源文件
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
- 修改资源文件,将Service的类型设置为"NodePort"类型并指定访问端口,以便将其暴露到集群外被进行访问,修改如下:
[root@centos7-master ~]# mv recommended.yaml kubernetes-dashboard.yaml
[root@centos7-master ~]# vim kubernetes-dashboard.yaml
...
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort
ports:
- port: 443
targetPort: 8443
nodePort: 30001
selector:
k8s-app: kubernetes-dashboard
...
- 在集群中创建资源:
[root@centos7-master ~]# kubectl apply -f kubernetes-dashboard.yaml
- 查看Pod对象
[root@centos7-master ~]# kubectl get pods -n kubernetes-dashboard
注意:我这边两个镜像一直pull不下来,手动pull下来也不起作用,网上查了资料,决定修改资源文件中的镜像地址,改成阿里云的地址,改后正常,操作如下
[root@centos7-master ~]# vim kubernetes-dashboard.yaml
...
kind: Deployment
apiVersion: apps/v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: kubernetes-dashboard
image: registry.cn-hangzhou.aliyuncs.com/google_containers/dashboard:v2.7.0 # 将此行的kubernetesui/dashboard:v2.7.0改为registry.cn-hangzhou.aliyuncs.com/google_containers/dashboard:v2.7.0
imagePullPolicy: Always
ports:
- containerPort: 8443
protocol: TCP
args:
- --auto-generate-certificates
- --namespace=kubernetes-dashboard
# Uncomment the following line to manually specify Kubernetes API server Host
# If not specified, Dashboard will attempt to auto discover the API server and connect
# to it. Uncomment only if the default does not work.
# - --apiserver-host=http://my-address:port
volumeMounts:
- name: kubernetes-dashboard-certs
mountPath: /certs
# Create on-disk volume to store exec logs
- mountPath: /tmp
name: tmp-volume
livenessProbe:
...
- 当所有Pod的状态都显示为"Running",说明Dashboard安装成功,在浏览器中访问"https://192.168.0.113:30001", 可以看到登录界面,如下:
- 创建一个服务账号并授予集群管理员权限
[root@centos7-master ~]# kubectl create serviceaccount admin -n kubernetes-dashboard
[root@centos7-master ~]# kubectl create clusterrolebinding admin --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:admin
根据服务账号创建Token:
[root@centos7-master ~]# kubectl create token admin -n kubernetes-dashboard
将输出的Token复制到输入框中,然后单击登录,进入Dashboard首页: