文章目录
- 一、etcd备份与恢复
- 1.1 kubeadm部署方式
- 1.1.1 备份
- 1.1.2 恢复
- 1.2 单etcd二进制部署方式
- 1.2.1 部署
- 1.2.2 备份
- 1.2.3 恢复
- 1.2.4 K8s集群二进制部署方式恢复
- 二、集群版本升级
- 2.1 升级master节点
- 2.2 升级node节点
- 三、网络策略
- 3.1 核心字段释义
- 3.2 测试案例
- 案例1:拒绝命名空间下所有Pod出入站流量
- 案例2:拒绝其他命名空间pod访问
- 案例3:允许其他命名空间pod访问指定应用
- 案例4:同一个命名空间下应用之间限制访问
- 案例5:只允许指定命名空间中的应用访问
- 案例6:限制端口范围
一、etcd备份与恢复
基本了解:
- K8s 使用etcd数据库实时存储集群中的数据,安全起见,一定要备份!
- 备份只需要在一个节点上备就可以了,每个节点上的数据是同步的;但是数据恢复是需要在每个节点上进行。
- ectd容器是与宿主机网络共享的,采用hostNetwork方式,2379数据端口就可以在宿主机上查看到。
- kubeadm方式部署的集群,其中etcd是通过静态pod方式部署启动,在/etc/kubernetes/manifests目录下有它的yaml文件,里面记录了启动镜像、版本、证书路劲、数据目录等内容。
注意事项:
- 使用yum安装的etcd版本比较低,因为etcd现有两个版本,2和3,两个版本之间的api改动较大,现在使用之前都需要先指定到3版本。
1.1 kubeadm部署方式
1.1.1 备份
1.安装etcd。
[root@k8s-master opt]# yum -y install etcd
2.查看当前pod,待会备份后删除它,再数据恢复查看效果。
3.备份,导出的数据文件是qingjun.db。
ETCDCTL_API=3 etcdctl snapshot save qingjun.db \
--endpoints=https://127.0.0.1:2379 \ ##指定etcd地址端口。
--cacert=/etc/kubernetes/pki/etcd/ca.crt \ ##指定etcd根证书。
--cert=/etc/kubernetes/pki/etcd/server.crt \ ##指定etcd客户端数字证书。
--key=/etc/kubernetes/pki/etcd/server.key ##指定key。
4.删除pod,恢复查看效果。
1.1.2 恢复
5.先停止api server 和etcd服务。因为是静态Pod部署,监控这个目录下的yaml文件,当把目录备份后就直接相当于停服。
[root@k8s-master manifests]# pwd
/etc/kubernetes/manifests
[root@k8s-master manifests]# mv /etc/kubernetes/manifests /etc/kubernetes/manifests.bck
[root@k8s-master manifests]# mv /var/lib/etcd /var/lib/etcd.bck
6.使用qingjun.db文件恢复数据到/var/lib/etcd目录。
[root@k8s-master opt]# ETCDCTL_API=3 etcdctl snapshot restore qingjun.db --data-dir=/var/lib/etcd
7.启动kube-apiserver和etcd容器。
[root@k8s-master opt]# mv /etc/kubernetes/manifests.bck /etc/kubernetes/manifests
8.查看结果,数据恢复。
1.2 单etcd二进制部署方式
1.2.1 部署
1.提前准备etcd二进制安装包,下载地址。
2.解压安装包。
[root@k8s-node2 opt]# tar zxf etcd-v3.5.1-linux-amd64.tar.gz
[root@k8s-node2 opt]# cd etcd-v3.5.1-linux-amd64/
[root@k8s-node2 etcd-v3.5.1-linux-amd64]# cp etcd etcdctl /usr/bin/
3.准备配置文件
[root@k8s-node2 etcd-v3.5.1-linux-amd64]# cat /etc/etcd.conf
ETCD_NAME="etcd" ##节点名称
ETCD_DATA_DIR="/var/lib/etcd" ##数据目录
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379" ##监听地址
ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379" ##别人连我的地址
4.设置为systemd系统服务。
[root@k8s-node2 etcd-v3.5.1-linux-amd64]# cat /usr/lib/systemd/system/etcd.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=/etc/etcd.conf
ExecStart=/usr/bin/etcd
Restart=on-failure
LimitNOFILE=65536
5.启动服务并设置开机启动
[root@k8s-node2 etcd-v3.5.1-linux-amd64]# systemctl daemon-reload
[root@k8s-node2 etcd-v3.5.1-linux-amd64]# systemctl start etcd
[root@k8s-node2 etcd-v3.5.1-linux-amd64]# systemctl enable etcd
6.查看etcd状态。
[root@k8s-node2 etcd-v3.5.1-linux-amd64]# etcdctl endpoint status --write-out=table
1.2.2 备份
1.查看etcd服务,需要提前部署。
2.备份。
##这里没有指定证书,所以就是http。
[root@k8s-node2 ~]# ETCDCTL_API=3 etcdctl snapshot save baimu.db --endpoints=http://127.0.0.1:2379
1.2.3 恢复
3.先停止etcd服务。
[root@k8s-node2 ~]# systemctl stop etcd
[root@k8s-node2 ~]# mv /var/lib/etcd /var/lib/etcd.bck
4.恢复数据到指定目录。
[root@k8s-node2 ~]# ETCDCTL_API=3 etcdctl snapshot restore baimu.db --data-dir=/var/lib/etcd
5.启动服务即可。
[root@k8s-node2 ~]# systemctl start etcd
1.2.4 K8s集群二进制部署方式恢复
- 上面演示的只是单etcd是二进制部署,一般情况下二进制部署都是成套的,也就是说所有组件都用二进制方式部署。所以在停止、启动服务时有点区别。
1、先暂停kube-apiserver和etcd。
systemctl stop kube-apiserver
systemctl stop etcd
mv /var/lib/etcd/default.etcd /var/lib/etcd/default.etcd.bak
2、在每个节点上恢复。
注意:不管哪种方式恢复数据,都是在每个节点上进行恢复。所以这里就需要指定集群信息。
ETCDCTL_API=3 etcdctl snapshot restore snap.db \
--name etcd-1 \ ##节点名称
--initial-cluster="etcd-1=https://192.168.31.71:2380,etcd-2=https://192.168.31.72:2380,etcd-3=https://192.168.31.73:2380" \ ##集群地址
--initial-cluster-token=etcd-cluster \
--initial-advertise-peer-urls=https://192.168.31.71:2380 \ ##当前恢复的etcd节点地址
--data-dir=/var/lib/etcd ##数据恢复到哪里,默认就是数据目录。
3、启动kube-apiserver和etcd
systemctl start kube-apiserver
systemctl start etcd
二、集群版本升级
升级思路:
- 先升级master1节点,再升级master2、master3等管理节点,再升级node1、node2等工作节点。
- 升级存在风险,所以需要先对升级的节点做数据备份。
- 升级时,先驱逐节点上的pod,在设置为不可调度。因为升级存在风险,若升级失败,也不会影响业务。
注意事项:
- 升级前必须备份所有组件及数据,例如etcd
- 千万不要跨多个小版本进行升级,例如从1.16升级到1.19
- 在测试环境经过多次演练、实操,没问题后才能上生产环境。
2.1 升级master节点
1.查找最新版本号。
[root@k8s-master bck]# yum list --showduplicates kubeadm
2.先升级kubeadm。
[root@k8s-master bck]# yum install -y kubeadm-1.26.3-0
3.驱逐node上的pod,且不可调度。
#ignore-daemonsets参数:忽略无法驱逐的pod。
[root@k8s-master bck]# kubectl drain k8s-master --ignore-daemonsets
4.查看该节点pod状态,检查是否驱逐成功。此时该节点没有任何pod业务,可开始升级。
5.查看集群是否可以升级。
[root@k8s-master bck]# kubeadm upgrade plan
6.升级。
[root@k8s-master bck]# kubeadm upgrade apply v1.26.3
7.升级kubelet和kubectl,和kubeadm版本要一致。
[root@k8s-master bck]# yum install -y kubelet-1.26.3-0 kubectl-1.26.3-0
8.重启kubelet,再次查看版本已经被升级到新版本。
[root@k8s-master bck]# systemctl daemon-reload
[root@k8s-master bck]# systemctl restart kubelet
9.取消不可调度,重新上线。
[root@k8s-master bck]# kubectl uncordon k8s-master
2.2 升级node节点
1.先查看当前版本。
2.升级kubeadm版本。
[root@k8s-node2 ~]# yum install -y kubeadm-1.26.3-0
3.驱逐node1上的pod,且不可调度。
kubectl drain k8s-node1 --ignore-daemonsets
3、升级kubelet配置
kubeadm upgrade node
4、升级kubelet和kubectl
yum install -y kubelet-1.26.3-0 kubectl-1.26.3-0
5、重启kubelet
systemctl daemon-reload
systemctl restart kubelet
6、取消不可调度,重新上线。
kubectl uncordon k8s-node1
三、网络策略
基本了解:
- 网络策略通过网络插件来实现,创建一个 NetworkPolicy 资源对象而没有控制器来使它生效的话,是没有任何作用的,而我们搭建K8s集群时安装的calico网络组件就支持网络策略。
- 默认情况下,K8s 集群网络没任何网络限制,Pod 可以与任何其他 Pod 通信,在某些场景下就需要进行网络控制,减少网络攻击面,提高安全性,这就会用到网络策略。
- 网络策略是一个K8s资源,需要管理员写yaml定义规则的,用于限制Pod出入流量,提供Pod级别和Namespace级别网络访问控制。
应用场景:
- 应用程序间的访问控制,例如项目A不能访问项目B的Pod。
- 开发环境命名空间不能访问测试环境命名空间Pod。
- 当Pod暴露到外部时,需要做Pod白名单。
- 多租户网络环境隔离。
网络策略工作流程:
- 使用kubectl提交yaml文件给api server创建Network Policy资源。
- api server 收到之后存到etcd数据库中。
- Policy Controller组件监控网络策略,同步并通知节点上程序。
- 节点上DaemonSet运行的程序从etcd中获取Policy,调用本地Iptables创建防火墙规则。
注意事项:
- calico网络组件是以Daemonset方式部署到每个节点,其中红色框的pod负责calico录入表的维护,网络策略的执行和下发。
- 有的网络组件没有这个红色个框的控制器,只有agent-pod。
- 也有特定需求是网络策略当前实现不了的,可以通过操作系统组件、准入控制器来实现。
3.1 核心字段释义
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy ##自定义网络策略名称。
namespace: default ##定义对哪个命名空间的Pod进行限制,这里就是对default命名空间下的pod生效。
spec:
podSelector: ##目标Pod,对哪个Pod生效。
matchLabels:
role: db ##根据标签选择。
policyTypes: ##策略类型。
- Ingress ##入站流量,谁能访问我。
- Egress ##出站流量,我能访问谁。
ingress:
- from: ##from是可以访问的白名单,可以来自于IP段、命名空间、Pod标签等,ports是可以访问的端口。
- ipBlock: ##可以访问我的IP段,除了 172.17.1.0/24 之外的所有 172.17.0.0/16网络中的pod都可以访问我。
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector: ##命名空间的标签为project=myproject,且其下pod标签为role=client的pod可以访问我。
matchLabels:
project: myproject
podSelector:
matchLabels:
role: client
- podSelector: ##任何名字空间中,标签为role=frontend的Pod可以访问我。
matchLabels:
role: frontend
ports: ##白名单能基于TCP协议访问我的6379端口。
- protocol: TCP
port: 6379
egress: ##我能访问10.0.0.0/24网段中的5978 TCP端口。
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
3.2 测试案例
案例1:拒绝命名空间下所有Pod出入站流量
- 需求:拒绝test命名空间下所有Pod入、出站流量。
- 解读:test命名空间下的pod不能访问别人,也不允许让别人访问test命名空间下的所有pod。
1.创建test命名空间,并生成一个deploy,名为nginx,在defalue空间生成一个测试pod,名为bs。
[root@k8s-master1 networkpolicy]# kubectl create ns test
[root@k8s-master1 networkpolicy]# kubectl create deployment nginx --image=nginx -n test
[root@k8s-master1 networkpolicy]# kubectl run bs --image=busybox -- sleep 24h
2.此时bs容器可以ping通nginx网络。
3.编写yaml文件,生成网络策略。
[root@k8s-master1 networkpolicy]# cat network1.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: qingjun1
namespace: test
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
[root@k8s-master1 networkpolicy]# kubectl apply -f network1.yaml
4.此时再用bs就ping不同nginx的网络。
案例2:拒绝其他命名空间pod访问
- 需求:test命名空间下所有pod可以互相访问,也可以访问其他命名空间Pod,但其他命名空间不能访问test命名空间Pod。
- 解读:test命名空间的pod可以访问别人,但别人不能访问它。
1.生成网络策略。
[root@k8s-master1 networkpolicy]# cat network2.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: qingjun2
namespace: test
spec:
podSelector: {}
policyTypes:
- Ingress
ingress:
- from:
- podSelector: {} # 匹配test命名空间所有pod,其他所有命名空间下的pod都不能访问我。
[root@k8s-master1 networkpolicy]# kubectl apply -f network2.yaml
2.测试效果。
案例3:允许其他命名空间pod访问指定应用
- 需求:允许其他命名空间访问test命名空间里的指定pod,但test命名空间的其他pod不能访问这个指定的pod。
- 解读:默认情况下是能访问test命名空间的pod,所以可以叠加使用两个网络策略。
1.生成第一个网络策略,允许所有命名空间下的pod可以访问test命名空间下的带有标签为app=nginx的pod。
[root@k8s-master1 networkpolicy]# cat network3.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: qingjun3
namespace: test
spec:
podSelector:
matchLabels:
app: nginx
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector: {} # 匹配所有命名空间的pod
[root@k8s-master1 networkpolicy]# kubectl apply -f network3.yaml
2.再添加第二个策略,禁止所有流量进出。此时两个网络策略共同起作用。
[root@k8s-master1 networkpolicy]# cat network1.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: qingjun1
namespace: test
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
[root@k8s-master1 networkpolicy]# kubectl apply -f network1.yaml
3.测试效果,其他命名空间下的pod可以访问text命名空间下标签为app=nginx的pod,同时test命名空间下的其他pod不能访问text命名空间下标签为app=nginx的pod。
案例4:同一个命名空间下应用之间限制访问
需求:将test命名空间中标签为app=nginx的pod隔离,只允许text命名空间下的标签为run=client1的pod访问它的80端口,其他命名空间的所有pod都不能访问。
1.生成网络策略。
[root@k8s-master1 networkpolicy]# cat network4.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: qingjun4
namespace: test
spec:
podSelector:
matchLabels:
app: nginx
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
run: client1
ports:
- protocol: TCP
port: 80
[root@k8s-master1 networkpolicy]# kubectl apply -f network4.yaml
2.测试效果。带有run=client1标签的pod可以访问到app=nginx标签的pod,带有run=bs标签的pod访问不了app=nginx标签的pod。
案例5:只允许指定命名空间中的应用访问
需求:限制dev命名空间标签为env=dev的pod,只允许prod命名空间中的pod访问,并且允许所有命名空间run=client1标签pod访问。
1.创建dev、prod命名空间,并在其下面创建2个pod。
[root@k8s-master1 networkpolicy]# kubectl create ns dev
[root@k8s-master1 networkpolicy]# kubectl create ns prod
[root@k8s-master1 networkpolicy]# kubectl run bs --image=busybox -n prod -- sleep 24h
[root@k8s-master1 networkpolicy]# kubectl create deployment dev --image=nginx -n dev
2.生成网络策略。
[root@k8s-master1 networkpolicy]# cat network5.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: qingjun5
namespace: dev
spec:
podSelector:
matchLabels:
env: dev
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector: # 既允许prod命名空间中的pod访问。
matchLabels:
kubernetes.io/metadata.name: prod
- namespaceSelector: {} # 也允许所有命名空间下pod标签为app=client1的pod访问。
podSelector:
matchLabels:
run: client1
[root@k8s-master1 networkpolicy]# kubectl apply -f network5.yaml
3.测试效果。
案例6:限制端口范围
需求:允许名字空间default中所有带有标签 role=db 的pod使用TCP协议与 10.0.0.0/24 范围内的 IP 通信,只要目标端口介于 32000 和 32768 之间就可以。
1.编写策略。
注意事项:
- endPort 字段必须等于或者大于 port 字段的值
- 只有在定义了 port 时才能定义 endPort。
- 两个字段的设置值都只能是数字。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: multi-port-egress
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 32000
endPort: 32768