k8s(Kubernetes)是由Gogle开源的容器编排引擎,可以用来管理容器化的应用程序和服务,k
- 高可用:系统在长时间内持续正常地运行,并不会因为某一个组件或者服务的故障而导致整个系统不可用
- 可扩展性:系统可以根据负载的变化来动态的扩展或缩减系统的资源,从而来提高系统的性能和资源利用率
k8s提供了自动重启、自动重建、自动修复提高集群的可用性,以下概念稍微了解即可,看一看直接实操,know what->know how->know why
核心概念
Pod组件
Pod是k8s的最小调度单元,一个Pod是一个或者多个应用容器的组合,Pod里的容器共享存储、网络、运行时配置等
Node节点组件
一个节点就是一个物理机或者虚拟机,一个节点上可以运行一个或多个Pod;一个集群至少2个节点,一个Master-Node
一个Worker-Node
一个节点上有三个组件:
- kubelet:管理和维护每个基点上的Pod,监控Worker-Node运行情况
- kube-proxy:网络代理和负载均衡
- container runtime:保障Pod运行,相当于Docker Engine
Master-Node:管理整个集群
-
kube-apiserver
:提供k8s集群的api接口服务,所有组件通过这个接口通信 -
ControllerManager
控制器管理器,负责管理集群中各种资源对象的状态,包括Node Controller
:负责在节点出现故障时进行通知和响应Job Controller
:检测代表一次性任务的Job对象,然后创建Pods来运行这些任务直至完成EndpointSlice Controller
:填充端点分片对象ServiceAccount Controller
:为新的命名空间创建默认服务账号
-
Scheduler
:调度器,负责监控k8s集群所有节点的资源使用情况,根据调度策略将Pod调度到合适的节点中运行 -
etcd
:键值存储系统,负责存储所有资源对象的状态信息 -
Cloud Controller manager
:云控制器管理器,负责与云平台的api交互
Worker-Node: 运行应用和服务
kubelet
:在每个节点上运行,接受收PodSpecs确保PodSpec中描述的容器处于运行状态且健康kube-proxy
:在每个节点上运行的网络代理,实现内外部的网络通信Container Runtime
:容器运行时,支持多容器运行,如Docker、Containerd等,目前推荐Containerd
,因为Docker太重了,对于k8s来说,只需要有一个容器运行时就可以,而Docker自带的还有网络这些用k8s的proxy就行
Cluster 集群组件
Cluster将多个节点组织到一起共同为系统提供服务的过程称为集群
Control Plane 控制平面组件
控制平面为集群做全局决策,比如资源调度、检测和响应集群事件,一般在Master-Node运行
Addons 插件
DNS
:集群内部的DNS服务dashbord
:web界面,便于管理应用和集群Container Resource Monitoring
:容器资源监控Cluster-level Logging
:集群日志记录Network Plugins
:负责为Pod分配ip并使它们能够在集群内部互相通信
Service 服务
可以将一组Pod封装成一个服务,这个服务可以通过统一的入口来访问,可以防止Pod被销毁或创建后ip改变导致失联
内部服务
像mysql、redis等只需要被集群内部访问不需要外部访问的就是内部服务
外部服务
像后端接口等需要被暴露给外部使用的就是外部服务
常用类型
ClusterIP
:默认方式,分配一个稳定的IP地址,即VIP,只能在集群内部访问NodePort
:在每个节点开放一个端口来暴露服务,可以在集群外部访问,通过NodeIP:NodePort访问(端口范围:30000~32767)LoadBalancer
:与NodePort类似,在每个节点启用一个端口来暴露服务。除此之外,K8s请求底层云平台的负载均衡器,把每个[Node IP]:[NodePort]作为后端添加进去ExternalName
:外部名称类型,将服务映射到一个外部服务域名上Headless
:无头类型,主要用于DNS解析和服务发现Ingress
:是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP和HTTPS,还可以提供负载均衡、SSL 终结和基于名称的虚拟托管ConfigMap
:API 对象,用来将非机密性的数据保存到键值对中Secret
:包含少量敏感数据(如密码、令牌或密钥)的对象,Secret 可以独立于使用它们的 Pod 创建,因此在创建、查看和编辑 Pod 的工作流程中,Secret(及其数据)被泄露的风险较小Volumes
:数据持久化存储Deployment
:部署有状态应用StatefulSet
:部署无状态应用
k8s架构
环境搭建
需要Matser Node虚拟机和Worker-Node虚拟机
安装kubectl
kubectl是使用K8s API 与K8s集群的控制面进行通信的命令行工具,kubectl安装到Matser Node节点的虚拟机
#安装kubectl
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
#查看安装
kubectl version --client
#卸载
sudo rm /usr/local/bin/kubectl
安装k8s
环境准备
- 这里使用kvm Linux虚拟机,使用vmware、virtbox、multipss是一样的,只是虚拟机不同罢了,喜欢哪个用哪个
kvm教程
网上有很多虚拟机安装教程,这里就不赘述了,本人使用debian12,你用啥Linux都可以,操作基本相同
1、配置要求:
- 你使用的电脑内存配置16G以上
- 虚拟机内存:2G或更多
- 虚拟机CPU:2G或更多
- 虚拟机硬盘:40或更多
- 虚拟机网络:每个虚拟机都能访问外网
- ssh连接正常:一般新装的虚拟机远程登陆默认关闭,先开启再克隆方便用远程连接工具操作
- 关闭防火墙:生产主机别关,我们学习关了方便操作,生产环境开放端口使用
- 关闭AppArmor(debian):
systemctl stop apparmor.service && systemctl disable apparmor.service
- 关闭SELinux(centos):
sed -i s#SELINUX=enforcing#SELINUX=disabled# /etc/selinux/config
不关下不了文件 - 关闭swap分区(必须):
swapoff -a && sed -ri 's/.*swap.*/#&/' /etc/fstab
- 同步时间:安装
sudo apt install ntpdate -y
校时ntpdate ntp.ntsc.ac.cn
2、克隆新的虚拟机,我们克隆三个
master-node
(worker1)worker-node
(worker2、worker3)
3、可以看到克隆的虚拟机和被克隆的虚拟机ip不同,因为dhcp默认自动分配了,如果配置过静态ip,修改ip即可。把三台主机的ip记住,经常使用!
4、使用你喜欢的工具远程连接上三台虚拟机,用你喜欢的方式给它们区分好
5、修改主机名,克隆的虚拟机主机名都是一样的,不改的话k8s显示一样的名字无法区分,分别在三台主机上设置,还记得吗,主机/虚拟机就是Node节点,在这一步记得每个虚拟机拍个快照,装错了方便修改
#worker1 master-node
hostnamectl set-hostname node1
#worker2 worker-node
hostnamectl set-hostname node2
#worker3 worker-node
hostnamectl set-hostname node3
#查看主机名
hostname
以下操作多台服务器命令一样,在windterm按下alt+w->alt+h
水平分屏,按下alt+w->alt+v
垂直分屏,然后ctrl+shift+m
添加到频道就可以同步多窗口输入了
6、安装containerd,喜欢Docker安装docker也可以,但是对于k8s来说,docker有的功能k8s也有,这里直接用官方建议的containerd
下载对应系统最新的containerdgithub
要是觉得三个一起下的慢就在本机下载了上传到三台服务器
#三台虚拟机下载containerd
wget https://github.com/containerd/containerd/releases/download/v1.7.18/containerd-1.7.18-linux-amd64.tar.gz
#解压到/usr/local目录
tar Cxzvf /usr/local containerd-1.7.18-linux-amd64.tar.gz
#检查
containerd -v
containerd默认不会自带runc(真正创建容器的程序),以及cni网络插件(容器之间网络通信)
|cni
#如法炮制,到上面链接下载runc、cni
wget https://github.com/opencontainers/runc/releases/download/v1.1.13/runc.amd64
wget https://github.com/containernetworking/plugins/releases/download/v1.5.1/cni-plugins-linux-amd64-v1.5.1.tgz
#安装runc.amd64
install -m 755 runc.amd64 /usr/local/sbin/runc
#安装cni,包名换成自己下的
mkdir -p /opt/cni/bin
tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.5.1.tgz
#检查
runc -v
配置systemd
#新建文件
vim /usr/local/lib/systemd/system/containerd.service
#把文件内容复制粘贴到新文件
https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
重新加载
systemctl daemon-reload
systemctl enable --now containerd
7、配置containerd
#新建文件夹
mkdir -p /etc/containerd
#生成配置文件
containerd config default > /etc/containerd/config.toml
#查看配置文件
cat /etc/containerd/config.toml
配置cgroup,vim /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
:set nu
显示行号,在139行改为true,或者输入/runc.options
定位(需要装vim,vi太难用了)
设置开机自启并启动
systemctl enable containerd && systemctl start containerd && systemctl status containerd
重启
sudo systemctl restart containerd
配置沙盒镜像,vim /etc/containerd/config.toml
,你也可以改成国内的(2024/6/25无法使用)
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.k8s.io/pause:3.2"
如
registry.aliyuncs.com/google_containers/pause:3.9
设置镜像加速器,设置自己的加速地址,阿里
如果使用cri-dockerd
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://ci8e67uo.mirror.aliyuncs.com"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
endpoint = ["https://registry.cn-hangzhou.aliyuncs.com/google_containers"]
重新加载
systemctl daemon-reload && systemctl restart containerd
8、配置网络
修改hosts,改成自己对应的ip,实际生产环境使用DNS服务器
cat >> /etc/hosts<<EOF
192.168.122.162 node1
192.168.122.191 node2
192.168.122.157 node3
EOF
ping node1
、ping node2
、ping node3
检查一下
修改内核参数
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
验证
#重启
sudo sysctl --system
#验证
sysctl net.ipv4.ip_forward
加载overlay网络驱动、br_netfilter启用网络过滤规则
modprobe overlay
modprobe br_netfilter
重启生效
init 6或者reboot
9、添加k8s源
Debian/Ununtu
添加国内下载源(二选一)
#更新并安装apt-transport-https
apt-get update && apt-get install -y apt-transport-https
#添加阿里镜像要多少版本就改v1.30
curl -fsSL https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/deb/Release.key |
gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
#添加
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/deb/ /" |
tee /etc/apt/sources.list.d/kubernetes.list
#更新
apt-get update
添加官方下载源(二选一)
导入 gpg key
apt-get update && apt-get install -y apt-transport-https
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
新建文件
vim /etc/apt/sources.list.d/kubernetes.list
#添加一下内容
deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://mirrors.tuna.tsinghua.edu.cn/kubernetes/apt kubernetes-xenial main
RHEL/CentOS
新建文件
vim /etc/yum.repos.d/kubernetes.repo
#添加内容
[kubernetes]
name=kubernetes
baseurl=https://mirrors.tuna.tsinghua.edu.cn/kubernetes/yum/repos/kubernetes-el7-$basearch
enabled=1
安装k8s
包管理器安装k8s(推荐)
# Debian/Ununtu
apt install -y kubelet kubeadm kubectl
# Centos
yum install -y kubelet kubeadm kubectl
源码包安装k8s(大多数linux适用,需要解决网络问题)
1、安装cni(前面已安装过就跳过)
#下载包
wget https://github.com/containernetworking/plugins/releases/download/v1.5.1/cni-plugins-linux-amd64-v1.5.1.tgz
#安装cni,包名换成自己下的
mkdir -p /opt/cni/bin
tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.5.1.tgz
2、安装 crictl(kubeadm/kubelet 容器运行时接口(CRI)所需)
#新建目录(估计不用,一般有这个目录)
mkdir -p /usr/local/bin
#下载包
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.30.0/crictl-v1.30.0-linux-amd64.tar.gz
#安装
tar zxvf crictl-v1.30.0-linux-amd64.tar.gz -C /usr/local/bin
#验证
crictl -v
#清理包
rm -f crictl-v1.30.0-linux-amd64.tar.gz
- kubeadm:用来初始化集群的指令
- kubelet:在集群中的每个节点上用来启动 Pod 和容器等
- kubectl:用来与集群通信的命令行工具
3、安装kubeadm,kubelet
查看ip
添加解析的ip到hosts,vim /etc/hosts
20.205.243.166 raw.githubusercontent.com
#进入目录
cd /usr/local/bin
#下载最新版kubeadm,kubelet
sudo curl -L --remote-name-all "https://dl.k8s.io/release/$(curl -sSL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/{kubeadm,kubelet}"
#授权
sudo chmod +x {kubeadm,kubelet}
#下载kubelet.service
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/v0.16.2/cmd/krel/templates/latest/kubelet/kubelet.service" | sed "s:/usr/bin:/usr/local/bin:g" | sudo tee /usr/lib/systemd/system/kubelet.service
#创建kubelet系统服务目录
sudo mkdir -p /usr/lib/systemd/system/kubelet.service.d
配置kubeadm
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/v0.16.2/cmd/krel/templates/latest/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:/usr/local/bin:g" | sudo tee /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
4、安装kubectl
#下载
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
#安装
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
#验证
kubectl version --client
集群配置
设置kubelet开机启动并自启
systemctl enable --now kubelet && systemctl start kubelet && systemctl status kubelet
master-node初始化
在线拉取
kubeadm config images pull
或
生成默认配置文件
生成默认配置文件
kubeadm config print init-defaults > kubeadm.yml
#编辑
vim kubeadm.yml
- advertiseAddress:master-node的ip
- imageRepository:改成阿里镜像源
- nodeRegistration.name:改为节点名,即master
- networking.serviceSubnet:service网络ip范围
修改以下三处,国内镜像地址目前用不了(2024/6/25)
拉取镜像,拉不了先解决这个问题
# 查看所需的镜像
kubeadm config images list --config kubeadm.yml
#拉取镜像
for img in `kubeadm config images list --config kubeadm.yml` ; do ctr i pull $img ; done
离线导入(历经两天的折磨,推荐此方法,要不就出国拉镜像)
#查看需要的镜像
kubeadm config images list
#在能访问外网的电脑,拉取镜像到本地
docker pull 镜像
#将本地镜像导出为tar包不指定版本默认最新
docker save -o front.tar 镜像
#上传服务器加载镜像
sudo ctr -n k8s.io images import front.tar
#查看镜像
sudo ctr -n k8s.io images ls
查看k8s本地镜像
sudo ctr -n k8s.io images ls
只在node1也就是worker1初始化就可以了,这个节点当作master-node也就是control-plan
kubeadm init \
--kubernetes-version 指定版本 \
--apiserver-advertise-address=master-node的ip \
--service-cidr=service网络ip,用于分配ip \
--pod-network-cidr=pod网络内部的ip,随便设置 \
--image-repository 镜像地址
先重启
systemctl restart containerd
比如我的,执行后会下依赖
kubeadm init \
--apiserver-advertise-address=192.168.122.162 \
--pod-network-cidr=10.200.0.0/16
初始化失败执行kubeadm reset
在master-node,普通用户执行,第二个框是root用户的操作,一般生产环境root不会随便给你,所以就提权执行
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
然后记住最后一个框的token内容,在你需要加入的节点执行,这里在worker1和worker2执行
kubeadm join 192.168.122.162:6443 --token 6kcxpv.cdad9rdrtgx9jcya \
--discovery-token-ca-cert-hash sha256:f0dcc8a0b5a0f6edacd2cc4ccbdc810d147a91efc788b1e86d5c95adf6adc1f5
token24消失失效,后续添加新节点,在master-node执行以下命令新建token
kubeadm token create --print-join-command
master-node获取节点,可以看到worker-node(node2、node3)也被加进来了
kubectl get nodes
master-node安装dns插件
在master-node创建配置
vim kube-flannel.yml
配置中的Network
改为自己设置的pod-network-cidr
的ip
kind: Namespace
apiVersion: v1
metadata:
name: kube-flannel
labels:
k8s-app: flannel
pod-security.kubernetes.io/enforce: privileged
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: flannel
name: flannel
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- nodes/status
verbs:
- patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
k8s-app: flannel
name: flannel
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: flannel
subjects:
- kind: ServiceAccount
name: flannel
namespace: kube-flannel
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: flannel
name: flannel
namespace: kube-flannel
---
kind: ConfigMap
apiVersion: v1
metadata:
name: kube-flannel-cfg
namespace: kube-flannel
labels:
tier: node
k8s-app: flannel
app: flannel
data:
cni-conf.json: |
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
net-conf.json: |
{
"Network": "10.200.0.0/16",
"EnableNFTables": false,
"Backend": {
"Type": "vxlan"
}
}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-flannel-ds
namespace: kube-flannel
labels:
tier: node
app: flannel
k8s-app: flannel
spec:
selector:
matchLabels:
app: flannel
template:
metadata:
labels:
tier: node
app: flannel
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
hostNetwork: true
priorityClassName: system-node-critical
tolerations:
- operator: Exists
effect: NoSchedule
serviceAccountName: flannel
initContainers:
- name: install-cni-plugin
image: docker.io/flannel/flannel-cni-plugin:v1.4.1-flannel1
command:
- cp
args:
- -f
- /flannel
- /opt/cni/bin/flannel
volumeMounts:
- name: cni-plugin
mountPath: /opt/cni/bin
- name: install-cni
image: docker.io/flannel/flannel:v0.25.4
command:
- cp
args:
- -f
- /etc/kube-flannel/cni-conf.json
- /etc/cni/net.d/10-flannel.conflist
volumeMounts:
- name: cni
mountPath: /etc/cni/net.d
- name: flannel-cfg
mountPath: /etc/kube-flannel/
containers:
- name: kube-flannel
image: docker.io/flannel/flannel:v0.25.4
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
resources:
requests:
cpu: "100m"
memory: "50Mi"
securityContext:
privileged: false
capabilities:
add: ["NET_ADMIN", "NET_RAW"]
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: EVENT_QUEUE_DEPTH
value: "5000"
volumeMounts:
- name: run
mountPath: /run/flannel
- name: flannel-cfg
mountPath: /etc/kube-flannel/
- name: xtables-lock
mountPath: /run/xtables.lock
volumes:
- name: run
hostPath:
path: /run/flannel
- name: cni-plugin
hostPath:
path: /opt/cni/bin
- name: cni
hostPath:
path: /etc/cni/net.d
- name: flannel-cfg
configMap:
name: kube-flannel-cfg
- name: xtables-lock
hostPath:
path: /run/xtables.lock
type: FileOrCreate
应用配置
kubectl apply -f kube-flannel.yml
新建一个窗口监控,执行watch -n 1 -d kubectl get pods -A
,每秒刷新一次数据