![](https://img-blog.csdnimg.cn/img_convert/25f7ff7e10eaac0da45de8f88293b59d.png)
1: 权限控制RBAC
创建名称 deployment-clusterrole 的 ClusterRole,该⻆⾊具备创建 Deployment、Statefulset、 Daemonset 的权限,在命名空间 app-team1 中创建名称为 cicd-token 的 ServiceAccount,绑定 ClusterRole 到 ServiceAccount,且限定命名空间为 app-team1。
kubectl create serviceaccount cicd-token -n app-team1
kubectl create clusterrole deployment-clusterrole —-verb=create —-resource=deployments,statefulsets,daemonsets
kubectl create rolebinding cicd-token-binding -n app-team1 —-clusterrole=deployment-clusterrole --serviceaccount=app-team1:cicd-token
#验证:
kubectl describe rolebinding cicd-clusterrole -n app-team1
kubectl describe rolebinding -n app-team1
笔记:
Kubernetes中完成授权工作的就是RBAC机制,RBAC授权规则是通过四种资源来进行配置。
Role:角色,其实是定义一组对Kubernetes资源(命名空间级别)的访问规则。
RoleBinding:角色绑定,定义了用户和角色的关系。
ClusterRole:集群角色,其实是定义一组对Kubernetes资源(集群级别,包含全部命名空间)的访问规则。
ClusterRoleBinding:集群角色绑定,定义了用户和集群角色的关系。
ClusterRole和ClusterRoleBinding
相比Role和RoleBinding,ClusterRole和ClusterRoleBinding有如下几点不同:
ClusterRole和Clusterkuk用定义namespace字段
KClusterRole可以定义集群级别的资源
Role和ClusterRole指定了可以对哪些资源做哪些动作,RoleBinding和ClusterRoleBinding将角色绑定到特定的用户、用户组或ServiceAccount上。如下图所示。
其中,最重要最常用的是如下四个ClusterRole。
view:拥有查看命名空间资源的权限
edit:拥有修改命名空间资源的权限
admin:拥有命名空间全部权限
cluster-admin:拥有集群的全部权限
使用kubectl describe clusterrole命令能够查看到各个规则的具体权限。
Role + RoleBinding (available in single Namespace, applied in single Namespace)
ClusterRole + ClusterRoleBinding (available cluster-wide, applied cluster-wide)
ClusterRole + RoleBinding (available cluster-wide, applied in single Namespace)
Role + ClusterRoleBinding (NOT POSSIBLE: available in single Namespace, applied cluster-wide)
2: 设置节点不可⽤
设置 ek8s-node-1 节点为不可⽤、重新调度该节点上的所有 pod
kubectl cordon ek8s-node-1
kubectl drain ek8s-node-1 --ignore-daemonsets --delete-emptydir-data --force
笔记:
cordon 停止调度(不可调度,临时从K8S集群隔离)
影响最小,只会将node标识为SchedulingDisabled不可调度状态。
之后K8S再创建的pod资源,不会被调度到该节点。
旧有的pod不会受到影响,仍正常对外提供服务。
drain方式是安全驱逐pod,会等到pod应用程序优雅停止后再删除该pod。
drain驱逐流程:先在Node节点删除pod,然后再在其他Node节点创建该pod。所以为了确保drain驱逐pod过程中不中断服务(即做到"无感知"地平滑驱逐),必须保证要驱逐的pod副本数大于1,并且采用了"反亲和策略"将这些pod调度到不同的Node节点上了!也就是说,在"多个pod副本+反亲和策略"的场景下,drain驱逐过程对容器服务是没有影响的。
kubectl drain: 会忽略那些不能杀死的系统类型的 pod。drain命令中需要添加三个参数:--force、--ignore-daemonsets、--delete-local-data
--force 当一些pod不是经 ReplicationController, ReplicaSet, Job, DaemonSet 或者 StatefulSet 管理的时候就需要用--force来强制执行 (例如:kube-proxy)
--ignore-daemonsets 无视DaemonSet管理下的Pod。即--ignore-daemonsets往往需要指定的,这是因为deamonset会忽略unschedulable标签(使用kubectl drain时会自动给节点打上不可调度标签),因此deamonset控制器控制的pod被删除后可能马上又在此节点上启动起来,这样就会成为死循环.因此这里忽略daemonset。
--delete-local-data 如果有mount local volumn的pod,会强制杀掉该pod。
3: 备份还原 etcd
备份https://127.0.0.1:2379上的 etcd 数据到 /var/lib/backup/etcd-snapshot.db,使⽤之前的⽂ 件/data/backup/etcd-snapshot-previous.db 还原 etcd,使⽤指定的 ca.crt 、 etcd-client.crt 、 etcd-client.key
CA 证书:/opt/KUIN00601/ca.crt
客户端证书:/opt/KUIN00601/etcd-client.crt
客户端密钥:/opt/KUIN00601/etcd-client.key
#ca cert key为测试环境
export ETCDCTL_API=3
etcdctl --endpoints https://127.0.0.1:2379 \
--cacert=/opt/KUIN00601/etcd/ca.crt \
--cert=/opt/KUIN00601/etcd-client.crt \
--key=/opt/KUIN00601/etcd-client.key \
snapshot save $HOME/old.db
kubectl run --image=nginx test #用于验证还原情况
#自定义 --data-dir 需要确保当前为空 cat /etc/kubernetes/manifests/etcd.yaml 确认 data-dir 路径
#如不指定 data-dir 还原成功后 可能仍继续用之前目录
mv /var/lib/etcd /var/lib/etcd.backup
export ETCDCTL_API=3
etcdctl --endpoints https://127.0.0.1:2379 \
--cacert=/opt/KUIN00601/etcd/ca.crt \
--cert=/opt/KUIN00601/etcd-client.crt \
--key=/opt/KUIN00601/etcd-client.key \
--data-dir=/var/lib/etcd \
snapshot restore $HOME/old.db
#重启静态pod显示效果,可以不实施,上一步不指定data-dir可能无效果。
mv /etc/kubernetes/manifests /etc/kubernetes/manifests.backup
mv /etc/kubernetes/manifests.backup /etc/kubernetes/manifests
笔记
执行时提示permission denied,命令前面加sudo
etcdctl --help:查看帮助
cacert:verify certificates of TLS-enabled secure servers using this CA bundle
cert:identify secure client using this TLS certificate file
key:identify secure client using this TLS key file
4: ⽹络策略- NetworkPolicy资源
在命名空间 fubar80 中创建⽹络策略 allow-port-from-namespace,只允许ns corp-net 中的 pod 连上 fubar 中 pod 的8080 端⼝,注意:这⾥有 2 个 ns ,⼀个为 fubar(⽬标pod的ns),另外⼀个为 my-app(访 问源pod的ns)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-port-from-namespace
namespace: fubar
spec:
podSelector:
matchLabels: {}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: corp-net # 查看my-app命名空间标签
podSelector: #可以不写,注意与namespace为同一规则
matchLabels: {}
ports:
- protocol: TCP
port: 8080
5: 创建Service
重新配置已有的 deployment front-end,添加⼀个名称为 http 的端⼝规范来公开现有容器nginx的端口80/TCP。创建名 称为 front-end-svc 的 service,暴露容器的 http 端⼝,配置service 的类别为NodePort
kubectl edit deployment front-end
#添加如下内容 kubectl explain deploy.spec.template.spec.containers.ports
ports:
- name: http
protocol: TCP
containerPort: 80
kubectl expose deployment front-end --type=NodePort --port=80 --target-port=http --name=front-end-svc
笔记
kubectl expose:将资源暴露为新的Kubernetes Service。
指定deployment、service、replicaset、replication controller或pod ,并使用该资源的选择器作为指定端口上新服务的选择器。deployment 或 replicaset只有当其选择器可转换为service支持的选择器时,即当选择器仅包含matchLabels组件时才会作为暴露新的Service。
type:Type for this service: ClusterIP, NodePort, or LoadBalancer. Default is 'ClusterIP'.
port:The port that the service should serve on. Copied from the resource being exposed, if unspecified
target-port:Name or number for the port on the container that the service should direct traffic to. Optional.
protocol:The network protocol for the service to be created. Default is 'TCP'.
说明: 需要注意的是,Service 能够将一个接收 port 映射到任意的 targetPort。 默认情况下,targetPort 将被设置为与 port 字段相同的值。
Pod 中的端口定义是有名字的,你可以在 Service 的 targetPort 属性中引用这些名称
发布服务(服务类型)
对一些应用的某些部分(如前端),可能希望将其暴露给 Kubernetes 集群外部的 IP 地址。
Kubernetes ServiceTypes 允许指定你所需要的 Service 类型,默认是 ClusterIP。
Type 的取值以及行为如下:
ClusterIP:通过集群的内部 IP 暴露服务,选择该值时服务只能够在集群内部访问。 这也是默认的 ServiceType。
NodePort:通过每个节点上的 IP 和静态端口(NodePort)暴露服务。NodePort 服务会路由到自动创建的 ClusterIP 服务。 通过请求 <节点 IP>:<节点端口>,你可以从集群的外部访问一个 NodePort 服务。
LoadBalancer:使用云提供商的负载均衡器向外部暴露服务。 外部负载均衡器可以将流量路由到自动创建的 NodePort 服务和 ClusterIP 服务上。
ExternalName:通过返回 CNAME 和对应值,可以将服务映射到 externalName字段的内容(例如,foo.bar.example.com)。 无需创建任何类型代理。
说明: 你需要使用 kube-dns 1.7 及以上版本或者 CoreDNS 0.0.8 及以上版本才能使用 ExternalName 类型。
你也可以使用 Ingress 来暴露自己的服务。 Ingress 不是一种服务类型,但它充当集群的入口点。 它可以将路由规则整合到一个资源中,因为它可以在同一 IP 地址下公开多个服务。
6: Ingress
创建⼀个新的nginx Ingress 资源,名称 ping,命名空间 ing-internal,使⽤ /hello 路径暴露服务 hello 的 5678 端⼝
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ping
namespace: ing-internal
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /hello
pathType: Prefix
backend:
service:
name: hello
port:
number: 5678
7: 扩容Deployment
扩容 deployment loadbalancer 为6 个pod
kubectl scale deployment --replicas=6 loadbalancer
8: 升级 kubernetes
升级 master 节点为1.26.0 ,升级前确保drain master 节点,不要升级worker node 、容器 manager、 etcd、 CNI插件、DNS 等内容
kubectl get nodes
ssh mk8s-master-0
kubectl cordon mk8s-master-0
kubectl drain mk8s-master-0 --ignore-daemonsets --force
#apt-mark unhold kubeadm kubectl kubelet
apt-get update
apt-cache policy kubeadm|grep 1.xxx
apt-get install -y kubeadm=1.26.0-00 kubelet=1.26.0-00 kubectl=1.26.0-00
#apt-mark hold kubeadm kubectl kubelet
kubeadm upgrade plan
kubeadm upgrade apply v1.26.0 --etcd-upgrade=false
systemctl daemon-reload && systemctl restart kubelet
kubectl uncordon mk8s-master-0
笔记:
⾸先 cordon、drain master节点,其次升级 kubeadm 并 apply 到最新版本,升级 kubelet 和 kubectl
apt-mark:可以对软件包进行设置(手动/自动 )安装标记,也可以用来处理软件包的 dpkg(1) 选中状态,以及列出或过滤拥有某个标记的软件包。
apt-mark常用命令
auto – 标记指定软件包为自动安装
manual – 标记指定软件包为手动安装
minimize-manual – Mark all dependencies of meta packages as automatically installed.
hold – 标记指定软件包为保留(held back),阻止软件自动更新
unhold – 取消指定软件包的保留(held back)标记,解除阻止自动更新
showauto – 列出所有自动安装的软件包
showmanual – 列出所有手动安装的软件包
showhold – 列出设为保留的软件包
apt-get update :更新源。update是更新软件列表,upgrade是更新软件
apt-get --help 查看帮助 https://cloud.tencent.com/developer/article/1484966
kubeadm upgrade plan 将检查您的集群是否处于可升级状态,并以用户友好的方式获取可升级的版本。
systemctl:daemon-reload: 重新加载某个服务的配置文件,如果新安装了一个服务,归属于 systemctl 管理,要是新服务的服务程序配置文件生效,需重新加载。
systemctl --help 查看帮助
9: 将Pod分配给节点
创建pod名称nginx-kusc0041,镜像nginx,调度该pod到disk=ssd的节点上
k run nginx-kusc0041 --image-nginx --dry-run-=client -oyaml > 9.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-kusc0041
spec:
containers:
- name: nginxk
image: nginx
nodeSelector: #add
disk: ssd #add
10: 创建名称为kucc1 的pod,pod中运⾏nginx和redis两个容器污点和容忍度
统计ready状态节点 要求不包括NoSchedule的节点,将数量写入/opt/KUSC00402/KUSC00402.txt
number=`kubectl describe nodes|grep Taints|grep -i -v NoSchedule |wc -l`
echo number > /opt/KUSC00402/KUSC00402.txt
笔记:
https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/taint-and-toleration/
11: 创建多容器的pod
创建名称为kucc1 的pod,pod中运⾏nginx、nginx、consul、memcached多容器
apiVersion: v1
kind: Pod
metadata:
name: kucc1
spec:
containers:
- name: nginx
image: nginx
- name: redis
image: redis
- name: consul
image: consul
- name: memcached
image: memcached
12: 创建 PersistentVolume
创建⼀个名为app-config的PV,PV的容量为2Gi,访问模式为ReadWriteMany,volume的类型 为hostPath,pv映射的hostPath为/srv/app-config⽬录
apiVersion: v1
kind: PersistentVolume
metadata:
name: app-config
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteMany
hostPath:
path: "/srv/app-config"
笔记:
根据https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-persistent-volume-storage/下的yaml文件创建,修改name、storage、accessModes、path
访问模式有:
ReadWriteOnce
卷可以被一个节点以读写方式挂载。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷。
ReadOnlyMany
卷可以被多个节点以只读方式挂载。
ReadWriteMany
卷可以被多个节点以读写方式挂载。
ReadWriteOncePod
卷可以被单个 Pod 以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用ReadWriteOncePod 访问模式。这只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本。
13:创建PersistentVolumeClaim与Pod
使⽤指定storageclass csi-hostpath-sc创建⼀个名称为pv-volume的 pvc,容量为10 Mi 创建名称为web-server的pod,将nginx 容器的/usr/share/nginx/html⽬录使⽤该pvc挂载 将上述pvc的⼤⼩从10Mi更新为70Mi,并记录本次变更
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-volume
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Mi
storageClassName: csi-hostpath-sc
apiVersion: v1
kind: Pod
metadata:
name: web-server
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: mypv
volumes:
- name: mypv
persistentVolumeClaim:
claimName: pv-volume
kubectl edit pvc pv-volume --save-config
14: 监控pod的⽇志
监控foobar pod中的⽇志 获取包含unable-to-access-website的⽇志,并将⽇志写⼊到/opt/KUTR00101 /foobar
kubectl logs foobar |grep unable-to-access-website > /opt/KUTR00101/foobar
15: sidecar 模式
添加⼀个sidecar容器(使⽤busybox 镜像)到已有的pod 11-factor-app中,确保sidecar容器能 够输出/var/log/11-factor-app.log的信息,使⽤volume挂载/var/log⽬录,确保sidecar能访问 11-factor-app.log ⽂件
kubectl get pod 11-factor-app - o yaml > sidecar-new.yaml
cp sidecar-new.yaml 15.yaml
kubectl delete pod 11-factor-app
vi 15.yaml
#编辑 15.yaml 添加sidecar容器以及给已有容器添加挂载
#1、给已有容器添加varlog挂载
# 修改volumeMounts下 name、 mountPath
#2、添加sidecar容器
# -name:sidecar
# image:busybox
# args:[/bin/sh,-c,"tail -f /var/log/11-factor-app.log"]
# volumeMounts:
# - name:varlog
# mountPath:/var/log
#3、定义varlog存储
# 修改 volumes:下 name emptyDir:{}
笔记
先用kubectl get podname -o yaml > podname.yaml 获取到yaml文件,然后删除旧的 pod;
再重新 copy 一个新的 yaml 添加 sidecar 容器,并在两个容器中都挂载 emtpyDir 到 /var/log目录,最后通过apply 生成带 sidecar 的 pod;
pod 正常拉起后,通过 kubectl logs 11-factor-app sidecar 确认能正常输入日志即可
16: 查看 cpu 使⽤率最⾼的 pod
查找label为name=cpu-loader的pod,筛选出cpu负载最⾼的那个pod,并将名称追加 到/opt/KUTR00401/KUTR00401 .txt
podName=`kubectl top pod -l name=cpu-loader -A --sort-by='cpu'`
echo podName > /opt/KUTR00401/KUTR00401.txt
17: 排查集群中故障节点
节点wk8s-node-0 状态为NotReady,查看原因并恢复其状态为Ready 确保操作为持久的
kubectl get nodes
ssh wk8s-node-0
sudo -i
systemctl status kubelet
systemctl enable kubelet
systemctl restart kubelet
kubectl status kubelet
kubectl get nodes
测试环境:
#1
kubectl create ns app-team1
#3
mkdir -p /var/lib/backup
mkdir -p /opt/KUIN00601/
chmod -R 777 /var/lib/backup
chmod -R 777 /opt/KUIN00601/
cp /etc/kubernetes/pki/etcd/ca.crt /opt/KUIN00601/ca.crt #cacert
cp /etc/kubernetes/pki/etcd/server.crt /opt/KUIN00601/etcd-client.crt #cert
cp /etc/kubernetes/pki/etcd/server.key /opt/KUIN00601/etcd-client.key #key
cd /opt/KUIN00601
chmod 777 *
#4
kubectl create ns fubar
kubectl create ns corp-net
#5
echo "apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: front-end
name: front-end
spec:
replicas: 1
selector:
matchLabels:
app: front-end
template:
metadata:
labels:
app: front-end
spec:
containers:
- image: nginx:1.21
name: nginx" > front-end.yaml
kubectl apply -f front-end.yaml
#6
kubectl create ns ing-internal
#7
kubectl create deployment loadbalancer --image=nginx --replicas=4 #不能写deploy
#13
echo "apiVersion: v1
kind: PersistentVolume
metadata:
name: csi-hostpath-sc
spec:
storageClassName: csi-hostpath-sc
capacity:
storage: 100Mi
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
persistentVolumeReclaimPolicy: Recycle
mountOptions:
- hard
- nfsvers=4.1
nfs:
server: 192.168.65.20
path: "/nfs"
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: csi-hostpath-sc
provisioner: example.com/external-nfs
reclaimPolicy: Delete
allowVolumeExpansion: True" > 13.yaml
kubectl apply -f 13.yaml
#15
echo "apiVersion: v1
kind: Pod
metadata:
name: 11-factor-app
spec:
containers:
- name: count
image: busybox
args:
- /bin/sh
- -c
- >
i=0;
while true;
do
echo "$(date) INFO $i" >> /var/log/legacy-app.log;
i=$((i+1));
sleep 1;
done"> 15-1.yaml
kubectl apply -f 15-1.yaml
rm 15-1.yaml
#16
wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
#修改components.yaml, deployment metrics-server 中增加 --kubelet-insecure-tls 参数
kubectl apply -f components.yaml