rbac授权
设置配置环境:
[student@node-1] $ kubectl config use-context k8s
Context
为部署管道创建一个新的ClusterRole并将其绑定到范围为特定的namespace 的特定 ServiceAccount .
Task
创建一个名为 deployment-clusterrole 且仅允许创建以下资源类型的新ClusterRole :
Deployment
StatefulSet
DaemonSet
在现有的 namespace app-team1 中创建一个名为 cicd-token 的新ServiceAccount 。
限于 namespace app-team1 , 将新的ClusterRole deployment-clusterrole 绑定到新的 ServiceAccount cicd-token 。
解题
kubectl config use-context k8s
kubectl create clusterrole deployment-clusterrole --verb=create --resource=deployments,daemonsets,statefulsets
kubectl create ns app-team1
kubectl create serviceaccount cicd-token -n app-team1
kubectl create rolebinding cicd-token --serviceaccount=app-team1:cicd-token --clusterrole=deployment-clusterrole -n app-team1
#验证
kubectl describe rolebinding cicd-token -n app-team1
Name: cicd-token
Labels: <none>
Annotations: <none>
Role:
Kind: ClusterRole
Name: deployment-clusterrole
Subjects:
Kind Name Namespace
---- ---- ---------
ServiceAccount cicd app-team1
节点维护-指定node节点不可用
设置配置环境:
[studentinode-1] $ kubectl config use-context ek8s
问题权重: 4%
Task
将名为ek8s-node-1 的node设置为不可用,并重新凋度该node上所有运行的pods
kubectl cordon ek8s-node-1
kubectl drain ek8s-node-1 --delete-emptydir-data --ignore-daemonsets --force
kubectl uncordon ek8s-node-1
K8s版本升级
设置配置环境:
[student@node-1] $ kubectl config use- context mk8s
Task
现有的Kubernetes集群正在运行版本1.23.1。仅将主节点上的所
有Kubernetes控制平面和节点组件升级到版本1.23.2。
确保在升级之前drain主节点,并在升级后uncordon主节点。
可使用以下命令通过ssh 连接到主节点:
[student@node-1] $| ssh master01
可使用以下命令在该主节点上获取更高权限:
[student@master01] $ sudo -i
另外,在主节点升级kubelet和kubectl。
kubectl config use-context mk8s
kubectl cordon master01
kubectl drain master01 --delete-emptydir-data --ignore-daemonsets -force
ssh master01
sudo -i
apt-get install kubeadm-1.23.2-00 -y
kubeadm upgrade plan
kubeadm upgrade apply v1.23.2 --etcd-upgrade=false # 题目要求不升级etcd
# 升级 kubelet 和 kubectl
apt-get install kubelet-l.23.2-00 kubectl-l.23.2-00 -y
systemctl restart kubelet
#设置为可调度
kubectl uncordon master01
# 查看升级结果
kubectl get node
etcd 数据备份恢复
此项目无需更改配置环境。但是,在执行此项目之前,请确保您已返回初始点:
[student@nk85- master-0] $ exit
Task
首先,为运行在https://127.0.0.1:2379上的现有etcd 实例创建快照并将快照保存到/data/backup/etcd-snapshot.db
为给定实例创建快照预计能在几秒钟内完成。如果该操i作似乎挂起,则命令可能有问题。用CTRL+C 来取消操作,然后重试。
然后还原位于/data/backup/etcd-snapshot-previous.db的现有先前快照。
提供了以下TLS证书和密钥,以通过etcdctl连接到服务
CA证书: /opt/KUIN00601/ca.crt
客户端证书: /opt/KUIN00601/etcd-client.crt
客户端密钥: /opt/KUIN00601/etcd-client.key
# 替换以上证书路径以及路径
# 备份
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key snapshot save /data/backup/etcd-snapshot.db
# 恢复
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key snapshot restore /data/backup/etcd-snapshot.db
网络策略NetworkPolicy
设置配置环境:
[studentinode-1] $ kubectl config use-context hk8s
Task
在现有的namespace my-app中创建一个名为allow-port-from-namespace 的新NetworkPolicy 。
确保新的NetworkPolicy 允许namespace echo 中的Pods来连 接到namespace my-app 中的Pods的9000端口 。
进一步确保新的 NetworkPolicy : 不允许对没有在监听端口9000的Pods的访问 不允许不来自namespace echo中的Pods的访问。
参考官方文档,复制yaml文件内容,修改
kubectl config use-context hk8s
#给命名空间打标签:
kubectl label ns echo project=echo
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-port-from-namespace #pod名称
namespace: myapp #被访问者的命名空间
spec:
podSelector: #这两行必须要写,或者也可以写成一行为podSelector: {}
matchLabels: {} # 注意matchLabels:与之间有一个空格
policyTypes:
- Ingress #策略影响入栈流量
ingress:
- from: #允许流量的来源
- namespaceSelector:
matchLabels:
project: echo #访问者的命名空间的标签label
- podSelector: {} #注意,这个不写。如果ingress里也写了- podSelector:,则会导致myapp中的pod可以访问my-app中pod的9000了,这样不满足题目要求不允许非来自 namespace echo中的Pods的访问
ports:
- protocol: TCP
port: 9000 #被访问者公开的端口
kubectl apply -f networkpolicy.yaml
networkpolicy.networking.k8s.io/allow-port-from-namespace created
四层负载均衡service
设置配置环境:
[student@node-1] $| kubectl config use- context k8s
Task
重新配置一个已经存在的front-end的deployment,在名字为nginx的容器里面添加一个端口配置
名字为http,暴露端口号为80,然后创建一个service,名字为front-end-svc,
暴露该deployment的http端口,并目service的类型为NodePort。
kubectl config use-context k8s
参考官方文档,按照需要edit deployment,添加端口信息
kubectl edit deployment front-end#注意 :set paste,防止上yaml文件空格错序。
# 添加如下配置,主要是在name为nginx的容器下
name: nginx
containerPort: 80
name: http
添加service:
kubectl expose deploy front-end --name=front-end-svc --port=80 --target-port=http --type=NodePort
七层负载均衡Ingress
设置配置环境:
[student@mnode-1] $ kubectl config use-context k8s
Task
如下创建一个新的nginx Ingress 资源:
名称: pong
Namespace: ing-internal使用服务端口5678 在路径/hello. 上公开服务hello
可以使用以下命令检查服务hello 的可用性,该命令应返回hello :
[student@node-1] $| curl -kL <INTERNAL_ IP>/hello
# 以下考试无需要操作
kubectl create ns ing-internal
kubectl create deployment hello --image=nginx --port=80 --namespace=ing-internal
kubectl expose deployment hello --port=5678 --target-port=80 --name=hello --namespace=ing-internal
kubectl exec -it hello-8fd7d4d77-2kdv9 -- /bin/bash -n ing-internal
echo "hello" > /usr/share/nginx/html/index.html
# 以下考试操作
cat 7.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: pong
namespace: ing-internal
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- http:
paths:
- path: /hello
pathType: Prefix
backend:
service:
name: hello
port:
number: 5678
kubectl apply -f ingerss.yaml
curl -kL <INTERNAL_ IP>/hello
Deployment管理pod扩缩容
设置配置环境:
[student@node-1] $ kubeotl corfig use- context k8s
Task
将loadbalancer的deployment管理的Pod的副本数扩容成6个
#以下考试不需要操作
kubectl create deployment loadbalancer --image=nginx --replicas=2
#以下考试操作
kubectl config use-context k8s
kubectl edit deployment loadbalancer
找到 replicas: 6 修改保存
或者
kubectl scale --replicas=5 deployment loadbalancer
pod指定节点部署
设置配置环境:
[student@node-1] $ kubectl config use-context k8s
Task
创建一个Pod,名字为nginx-kusc00401,镜像地址是nginx,调度到具有disk=spinning标签的节点上
按如下要求调度一个 pod:
名称: nginx-kusc00401
Image: nginx
Node selector: disk=spinning
# 以下考试无需要操作
kubectl label node node2 disk=spinning
# 以下考试操作
kubectl config use-context k8s
cat 9.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-kusc00401
spec:
containers:
- name: nginx
image: nginx
nodeSelector:
disk: spinning
kubectl apply -f 9.yaml
检查可用节点数量
设置配置环境:
[student@node-1] $ kubectl config use-context k8s
Task
检查有多少worker nodes已准备就绪(不包括被打上Taint:NoSchedule的节点),并将数量写入
/opt/KUSC00402/kusc00402.txt
kubectl config use-context k8s
kubectl get nodes | grep -w 'Ready' | wc -l
root@master1:~# kubectl describe nodes node1 master1| grep 'Taint' | grep NoSchedule | wc -l
2
2-1 = 有多少节点为Ready状态 (不包括被打上 Taint: NoSchedule 的节点)
root@master1:/opt/KUSC00402# echo "1" >> /opt/KUSC00402/kusc00402.txt
或者
kubectl describe nodes $(kubectl get nodes | grep Ready| awk '{print $1}') | grep Tain | grep -vc NoSchedule > /opt/KUSC00402/kusc00402.txt
一个pod封装多个容器
设置配置环境:
[student@node-1] $ kubectl config use-context k8s
Task
创建一个名为kucc1的pod, 在pod里面分别为以下每个images单独运行一个app container (可能会有1-4个images) :
nginx + redis + memcached+consul
kubectl config use-context k8s
cat 11.yaml
kind: Pod
apiVersion: v1
metadata:
name: kubcc1
spec:
containers:
- name: nginx
image: nginx
- name: redis
image: redis
- name: memcached
image: memcached
- name: consul
image: consul
kubectl apply -f 11.yaml
持久化存储卷PersistentVolume
设置配置环境:
[student@node-1] $| kubectl config use-context hk8s
Task
创建名为app-data 的persistent volume,容量为2Gi,访问模式为ReadWriteOnce 。volume 类型为hostPath, 位于/srv/app-data
kubectl config use-context hk8s
cat 12.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: app-data
spec:
capacity:
storage: 2Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/srv/app-data"
kubectl apply -f 12.yaml
PersistentVolumeClaim
设置配置环境:
[student@node-1] $ kubectl config use- context ok8s
Task
创建一个名字为pv-volume的pvc,指定storageClass为csi-hostpath-sc,大小为10Mi然后创建一个新的Pod,名字为web-server,镜像为nginx,并目挂载该PVC至/usr/share/nginx/html,挂载的权限为ReadWriteOnce。之后通过kubectl edit或者kubectl path将pvc改成70Mi,并目记录修改记录
创建一个新的PersistentVolumeClaim ;
名称: pv-volume
Class: csi-hostpath-sc
容量: 10Mi
创建一个新的Pod, 此Pod将作为volume挂载到
PersistentVolumeClaim :
名称: web-server
Image: nginx
挂载路径: /usr/share/nginx/html
配置新的pod,以对volume具有ReadWriteOnce权限。
最后,使用kubectl edit 或kubectl patch将PersistentVolumeClaim的容量扩展为70Mi,并记录此更改。
kubectl config use- context ok8s
# cat 12.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pv-volume
spec:
storageClassName: csi-hostpath-sc
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Mi
---
apiVersion: v1
kind: Pod
metadata:
name: web-server
spec:
volumes:
- name: pv-volume
persistentVolumeClaim:
claimName: pv-volume
containers:
- name: web-server
image: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
kubectl apply -f 12.yaml
# 扩容 PVC 容量
kubectl edit pvc pv-volume –-record
修改以下:
storage: 10Mi
或者
kubectl edit pvc pv-volume --save-config
查看pod日志
设置配置环境:
[student@node-1] $ kubectl config use-context k8s
Task
监控名为foobar的Pod的日志,
并过滤出具有unable-access-website 信息的行,
然后将写入到/opt/KUTR00101/foobar
kubectl config use-context k8s
kubectl logs foobar | grep unable-access-website > /opt/KUTR00101/foobar
Sidecar代理
设置配置环境:
[studentnode-1] $ kubectl config use- context k8s
Context
将一个现有的Pod集成到Kubernetes的内置日志记录体系结构中(例如kubectl logs) 。添加streaning sidecar容器是实现此要求的一种好方法。
Task
使用busybox Image来将名为sidecar的sidecar容器添加到现有的Pod legacy-app 中。新的sidecar容器必须运行以下命令:
/bin/sh -c tail -n+1 -f /var/log/legacy-app.log
使用安装在/var/log的Volume,使日志文件legacy-app.log可用于sidecar容器。
除了添加所需的volume mount以外,请勿更改现有容器的规格。
kubectl config use-context k8s
Kubectl apply -f legacy-app.yaml
Kubectl get pods legacy-app -oyaml > c-sidecar.yaml
Vim c-sidecar.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
cni.projectcalico.org/podIP: 10.244.166.161/32
cni.projectcalico.org/podIPs: 10.244.166.161/32
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"legacy-app","namespace":"default"},"spec":{"containers":[{"args":["/bin/sh","-c","i=0; while true; do \n echo \"$i: $(date)\" \u003e\u003e /var/log/legacy-app.log; \n sleep 1; \ndone\n"],"image":"busybox","name":"count"}]}}
creationTimestamp: "2023-02-15T08:49:48Z"
name: legacy-app
namespace: default
resourceVersion: "107258"
uid: 7f3d5fc4-13c6-40e3-afad-c0cdad938afd
spec:
containers:
- args:
- /bin/sh
- -c
- "i=0; while true; do \n echo \"$i: $(date)\" >> /var/log/legacy-app.log;
\n sleep 1; \ndone\n"
image: busybox
imagePullPolicy: Always
name: count
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/log
name: logs
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-6wj2s
readOnly: true
- name: sidecar
image: busybox
imagePullPolicy: IfNotPresent
args: ['/bin/sh', '-c', 'tail -n+1 -f /var/log/legacy-app.log']
volumeMounts:
- name: logs
mountPath: /var/log
dnsPolicy: ClusterFirst
enableServiceLinks: true
nodeName: node1
preemptionPolicy: PreemptLowerPriority
priority: 0
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
tolerations:
- effect: NoExecute
key: node.kubernetes.io/not-ready
operator: Exists
tolerationSeconds: 300
- effect: NoExecute
key: node.kubernetes.io/unreachable
operator: Exists
tolerationSeconds: 300
volumes:
- name: logs
emptyDir: {}
- name: kube-api-access-6wj2s
projected:
defaultMode: 420
sources:
- serviceAccountToken:
expirationSeconds: 3607
path: token
- configMap:
items:
- key: ca.crt
path: ca.crt
name: kube-root-ca.crt
- downwardAPI:
items:
- fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
path: namespace
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2023-02-15T08:49:48Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2023-02-15T08:49:56Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2023-02-15T08:49:56Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2023-02-15T08:49:48Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: docker://155bec5a7d481a50d7663a97c8778937b2b64aa329ced21a4c282a55bd7c35fd
image: busybox:latest
imageID: docker-pullable://busybox@sha256:7b3ccabffc97de872a30dfd234fd972a66d247c8cfc69b0550f276481852627c
lastState: {}
name: count
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2023-02-15T08:49:56Z"
hostIP: 192.168.22.144
phase: Running
podIP: 10.244.166.161
podIPs:
- ip: 10.244.166.161
qosClass: BestEffort
startTime: "2023-02-15T08:49:48Z"
kubectl delete -f c-sidecar.yaml --force --grace-period=0
kubectl apply -f c-sidecar.yaml
kubectl logs legacy-app -c sidecar
查看pod的cpu
设置配置环境:
[student@node-1] $ kubectl config use- context k8s
Task
通过pod label name=cpu-use,找到运行时占用大量CPU的pod,
并将占用CPU最高的pod名称写入文件
/opt/KUTR00401/KUTR00401.txt (已存在)
注意他没有说指定namespace。所以需要使用-A指定所以namespace
kubectl config use-context k8s
kubectl top pod -l name=cpu-use --sort-by="cpu" –A # 然后将第一个 Pod 名称写到文件
NAMESPACE NAME CPU(cores) MEMORY(bytes)
kube-system coredns-54d67798b7-hl8xc 7m 8Mi
kube-system coredns-54d67798b7-m4m2q 6m 8Mi
echo "<podname>" > /opt/opt/KUTR000401/KUTR00401.txt
echo "coredns-54d67798b7-hl8xc" > /opt/KUTR000401/KUTR00401.txt
集群故障排查-kubelet的故障
设置配置环境:
[student@node-1] $ kubectl config use-context wk8s
Task
名为wk8s-node-0 的Kubernetes worker node处于NotReady状态。
让其他恢复至正常状态,并确认所有的更改开机自动完成
可使用以下命令通过ssh 连接到故障node:
[student@node-1] $ ssh wk8s-node-0
可使用以下命令在该node上获取更高权限:
[student@w8ks-node-0] $ sudo -i
kubectl config use-context wk8s
kubectl get node
ssh wk8s-node-0
sudo -i
systemctl status kubelet
systemctl restart kubelet
systemctl enable kubelet
# 退出wk8s-node-0,退回到student@node-1
# 不要输入exit多了,否则会退出考试环境的。