文章目录
题目1 HPA
设置配置环境 kubectl config use-context k8s
Task
在 autoscale namespace 中创建一个名为 apache-server 的新HorizontalPodAutoscaler(HPA)。
此 HPA 必须定位到 autoscale namespace 中名为apache-server 的现有 Deployment 。
- 将 HPA 设置为每个 Pod 的 CPU 使用率旨在 50% 。
- 将其配置为至少有 1 个Pod,且不超过 4 个 Pod 。
- 此外,将缩小稳定窗口设置为 30 秒。
官网答案:https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/
练习环境
vim apache-server-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: apache-server
namespace: autoscale
spec:
selector:
matchLabels:
run: apache-server
template:
metadata:
labels:
run: apache-server
spec:
containers:
- name: apache-server
image: registry.cn-shenzhen.aliyuncs.com/cookcodeblog/hpa-example
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
resources:
limits:
cpu: 500m
requests:
cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
name: apache-server
namespace: autoscale
labels:
run: apache-server
spec:
ports:
- port: 80
selector:
run: apache-server
安装metric-server
wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml -O metrics-server-components.yaml
vim metrics-server-components.yaml
root@k8s-master1:~/log# cat components.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rbac.authorization.k8s.io/aggregate-to-edit: "true"
rbac.authorization.k8s.io/aggregate-to-view: "true"
name: system:aggregated-metrics-reader
rules:
- apiGroups:
- metrics.k8s.io
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
rules:
- apiGroups:
- ""
resources:
- nodes/metrics
verbs:
- get
- apiGroups:
- ""
resources:
- pods
- nodes
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server-auth-reader
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: extension-apiserver-authentication-reader
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: metrics-server:system:auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
k8s-app: metrics-server
name: system:metrics-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:metrics-server
subjects:
- kind: ServiceAccount
name: metrics-server
namespace: kube-system
---
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
ports:
- name: https
port: 443
protocol: TCP
targetPort: https
selector:
k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
k8s-app: metrics-server
name: metrics-server
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: metrics-server
strategy:
rollingUpdate:
maxUnavailable: 0
template:
metadata:
labels:
k8s-app: metrics-server
spec:
containers:
- args:
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- --kubelet-use-node-status-port
- --metric-resolution=15s
- --kubelet-insecure-tls
image: registry.aliyuncs.com/google_containers/metrics-server:v0.6.4
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /livez
port: https
scheme: HTTPS
periodSeconds: 10
name: metrics-server
ports:
- containerPort: 4443
name: https
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /readyz
port: https
scheme: HTTPS
initialDelaySeconds: 20
periodSeconds: 10
resources:
requests:
cpu: 100m
memory: 200Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
volumeMounts:
- mountPath: /tmp
name: tmp-dir
nodeSelector:
kubernetes.io/os: linux
priorityClassName: system-cluster-critical
serviceAccountName: metrics-server
volumes:
- emptyDir: {}
name: tmp-dir
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
labels:
k8s-app: metrics-server
name: v1beta1.metrics.k8s.io
spec:
group: metrics.k8s.io
groupPriorityMinimum: 100
insecureSkipTLSVerify: true
service:
name: metrics-server
namespace: kube-system
version: v1beta1
versionPriority: 100
执行部署命令
kubectl apply -f metrics-server-components.yaml
查看hpa相关信息
查看metrics-server 的pod状态
kubectl -n kube-system get pods -l k8s-app=metrics-server
答案(考试时需要做的)
第一步:创建hpa规则
kubectl autoscale deployment apache-server -n autoscale --cpu-percent=50 --min=1 --max=4
命令记不住可以查帮助
kubectl autoscale --help
Usage:
kubectl autoscale (-f FILENAME | TYPE NAME | TYPE/NAME) [--min=MINPODS] --max=MAXPODS [--cpu-percent=CPU] [options]
HPA(Horizontal Pod Autoscaler)创建成功了,如果 TARGETS 显示 (unknown)>/50%,说明它还没拿到当前 CPU 利用率数据,或者metric-server没有安装成功。
metric-server安装之后,就能看到 TARGETS 显示 0%/50%了
增加 CPU 负载,查看负载节点数目
vim load.yml
apiVersion: v1
kind: Pod
metadata:
name: load-generator
spec:
containers:
- name: load-tester
image: registry.cn-hangzhou.aliyuncs.com/acs/busybox:latest
command:
- /bin/sh
- -c
- |
echo "Starting load generation..."
while true; do
wget -q -O- http://10.100.68.202:80
sleep 0.01
done
kubectl apply -f load.yml
hpa规则已经生效,最少是1个,最多是4个
删掉load-generator,检测4个如何变1个
第二步:将缩小稳定窗口设置为 30 秒。
kubectl edit hpa -n autoscale apache-server
行为策略
behavior:
scaleDown:
stabilizationWindowSeconds: 30
题目2 ingress
设置配置环境 kubectl config use-context k8s (视频:0:49:17)
Task
如下创建一个新的 nginx ingress 资源:
- 名称:pong
- namespace: ing-internal
- 使用服务端口 8080 在路径/hello上公开服务 hello
- 可以使用以下命令检查服务 hello 的可用性,该命令返回 hello:
curl -kL http://example.org/echo/
先检查是否有ingressclass的资源
首先,要看看是否有ingressclass的资源,没有的话需要自己创建
在官网里搜索 ingress,
之后在页面搜索Default IngressClass找到相应的yaml文件复制粘贴即可。
default-ingressclass.yaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
labels:
app.kubernetes.io/component: controller
name: nginx-example
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: k8s.io/ingress-nginx
使用 default 里的例子,这里 ingressclass 使用什么名字(name: nginx-example),后面就要用什么名字,需要保持一致。
安装 ingressController
安装ingressController
apiVersion: v1
kind: Namespace
metadata:
labels:
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
name: ingress-nginx
---
apiVersion: v1
automountServiceAccountToken: true
kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx
namespace: ingress-nginx
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-admission
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx
namespace: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
- pods
- secrets
- endpoints
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- networking.k8s.io
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- networking.k8s.io
resources:
- ingressclasses
verbs:
- get
- list
- watch
- apiGroups:
- coordination.k8s.io
resourceNames:
- ingress-nginx-leader
resources:
- leases
verbs:
- get
- update
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- create
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- discovery.k8s.io
resources:
- endpointslices
verbs:
- list
- watch
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-admission
namespace: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
- namespaces
verbs:
- list
- watch
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- networking.k8s.io
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- networking.k8s.io
resources:
- ingresses/status
verbs:
- update
- apiGroups:
- networking.k8s.io
resources:
- ingressclasses
verbs:
- get
- list
- watch
- apiGroups:
- discovery.k8s.io
resources:
- endpointslices
verbs:
- list
- watch
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-admission
rules:
- apiGroups:
- admissionregistration.k8s.io
resources:
- validatingwebhookconfigurations
verbs:
- get
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx
namespace: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ingress-nginx
subjects:
- kind: ServiceAccount
name: ingress-nginx
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-admission
namespace: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
name: ingress-nginx-admission
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ingress-nginx
subjects:
- kind: ServiceAccount
name: ingress-nginx
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-admission
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: ingress-nginx-admission
subjects:
- kind: ServiceAccount
name: ingress-nginx-admission
namespace: ingress-nginx
---
apiVersion: v1
data:
allow-snippet-annotations: "true"
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-controller
namespace: ingress-nginx
---
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
externalTrafficPolicy: Local
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- appProtocol: http
name: http
port: 80
protocol: TCP
targetPort: http
- appProtocol: https
name: https
port: 443
protocol: TCP
targetPort: https
selector:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
type: LoadBalancer
---
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-controller-admission
namespace: ingress-nginx
spec:
ports:
- appProtocol: https
name: https-webhook
port: 443
targetPort: webhook
selector:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
minReadySeconds: 0
revisionHistoryLimit: 10
selector:
matchLabels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
strategy:
rollingUpdate:
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
spec:
containers:
- args:
- /nginx-ingress-controller
- --publish-service=$(POD_NAMESPACE)/ingress-nginx-controller
- --election-id=ingress-nginx-leader
- --controller-class=k8s.io/ingress-nginx
- --ingress-class=nginx
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- --validating-webhook=:8443
- --validating-webhook-certificate=/usr/local/certificates/cert
- --validating-webhook-key=/usr/local/certificates/key
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: LD_PRELOAD
value: /usr/local/lib/libmimalloc.so
image: registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:v1.8.2
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
exec:
command:
- /wait-shutdown
livenessProbe:
failureThreshold: 5
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: controller
ports:
- containerPort: 80
name: http
protocol: TCP
- containerPort: 443
name: https
protocol: TCP
- containerPort: 8443
name: webhook
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources:
requests:
cpu: 100m
memory: 90Mi
securityContext:
allowPrivilegeEscalation: true
capabilities:
add:
- NET_BIND_SERVICE
drop:
- ALL
runAsUser: 101
volumeMounts:
- mountPath: /usr/local/certificates/
name: webhook-cert
readOnly: true
dnsPolicy: ClusterFirst
nodeSelector:
kubernetes.io/os: linux
serviceAccountName: ingress-nginx
terminationGracePeriodSeconds: 300
volumes:
- name: webhook-cert
secret:
secretName: ingress-nginx-admission
---
apiVersion: batch/v1
kind: Job
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-admission-create
namespace: ingress-nginx
spec:
template:
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-admission-create
spec:
containers:
- args:
- create
- --host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc
- --namespace=$(POD_NAMESPACE)
- --secret-name=ingress-nginx-admission
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v20230407
imagePullPolicy: IfNotPresent
name: create
securityContext:
allowPrivilegeEscalation: false
nodeSelector:
kubernetes.io/os: linux
restartPolicy: OnFailure
securityContext:
fsGroup: 2000
runAsNonRoot: true
runAsUser: 2000
serviceAccountName: ingress-nginx-admission
---
apiVersion: batch/v1
kind: Job
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-admission-patch
namespace: ingress-nginx
spec:
template:
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-admission-patch
spec:
containers:
- args:
- patch
- --webhook-name=ingress-nginx-admission
- --namespace=$(POD_NAMESPACE)
- --patch-mutating=false
- --secret-name=ingress-nginx-admission
- --patch-failure-policy=Fail
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: registry.cn-hangzhou.aliyuncs.com/google_containers/kube-webhook-certgen:v20230407
imagePullPolicy: IfNotPresent
name: patch
securityContext:
allowPrivilegeEscalation: false
nodeSelector:
kubernetes.io/os: linux
restartPolicy: OnFailure
securityContext:
fsGroup: 2000
runAsNonRoot: true
runAsUser: 2000
serviceAccountName: ingress-nginx-admission
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: nginx
spec:
controller: k8s.io/ingress-nginx
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
labels:
app.kubernetes.io/component: admission-webhook
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.8.2
name: ingress-nginx-admission
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
service:
name: ingress-nginx-controller-admission
namespace: ingress-nginx
path: /networking/v1/ingresses
failurePolicy: Fail
matchPolicy: Equivalent
name: validate.nginx.ingress.kubernetes.io
rules:
- apiGroups:
- networking.k8s.io
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- ingresses
sideEffects: None
部署 hello 服务和 Deployment, (准备练习环境,考试无需此操作)
vim hello-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello
namespace: ing-internal
spec:
replicas: 1
selector:
matchLabels:
app: hello
template:
metadata:
labels:
app: hello
spec:
containers:
- name: hello
image: docker.m.daocloud.io/library/python:3.9-alpine
command: ["sh", "-c", "echo 'hello' > /tmp/index.html && python3 -m http.server 8000 --directory /tmp"]
ports:
- containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
name: hello
namespace: ing-internal
spec:
selector:
app: hello
ports:
- port: 8080
targetPort: 8000
手动拉取镜像
ctr -n k8s.io images pull docker.m.daocloud.io/library/python:3.9-alpine
应用资源:
kubectl apply -f hello-deploy.yaml
验证:
kubectl get pod -n ing-internal
kubectl get svc -n ing-internal
答案:
第一步:创建命名空间
kubectl create namespace ing-internal
第二步:创建新的 nginx ingress 资源
(考试时的重点操作)
下面 annotations 及下面的一行,练习的时候注释,考试不注释
创建文件 pong-ingress.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:
- host: example.org
http:
paths:
- path: /echo
pathType: Prefix
backend:
service:
name: hello
port:
number: 8080
应用
kubectl apply -f pong-ingress.yaml
Ingress 资源不会写,那就复制官网的模板:
查看确认:
kubectl describe ingress pong -n ing-internal
练习环境这里需要设置本地 hosts 映射
找到 Ingress Controller 所在节点 IP:
kubectl get pods -n ingress-nginx -o wide
kubectl get nodes -o wide
本机master节点上添加本地映射 /etc/hosts:
echo "192.168.31.102 example.org" >> /etc/hosts
也就是说,我们配置的pong-ingress.yaml资源是由ingress-nginx-controller控制的,所以要找到ingress-nginx-controller运行节点相应的ip
第三步:最终测试
curl http://example.org:31580/echo/
curl -kL http://example.org/echo/
题目3 sidecar
设置配置环境 kubectl config use-context k8s,
Context
您需要将一个传统应用程序集成到 Kubernetes 的日志架构(例如 kubectllogs)中。
实现这个要求的通常方法是添加一个流式传输并置容器。Task
更新现有的 legacy-app pod,
将使用 busybox:stable 镜像,且名为 sidecar 的并置容器,添加到现有的Pod 。
新的并置容器必须运行以下命令:/bin/sh -c “tail -n+1 -f /var/log//legacy-app.log”
使用挂载在 /var/log 的 Volume,使日志文件 legacy-app.log 可供并置容器使用。
除了添加所需的卷挂载之外,请勿修改现有容器的规范。
要点总结
你要做的是:
- 在现有的名为 legacy-app 的 Pod 中:
添加一个名为 sidecar 的容器,使用镜像 busybox:stable;- 该 sidecar 容器运行的命令是:
/bin/sh -c “tail -n+1 -f /var/log/legacy-app.log”- 它需要通过挂载在 /var/log 的 Volume,读取主容器生成的日志。
- 不能修改已有容器,只能添加 sidecar 容器 和 卷定义、挂载点。
改:
如果题目不是 pod 是 deployment 的话一样的做法。
准备练习环境
vim legacy-app.yaml
apiVersion: v1
kind: Pod
metadata:
name: legacy-app
spec:
containers:
- name: legacy
image: registry.aliyuncs.com/google_containers/busybox
command: ["/bin/sh", "-c"]
args: ["while true; do echo 'log line' >> /var/log/legacy-app.log; sleep 5; done"]
volumeMounts:
- name: log-volume
mountPath: /var/log
volumes:
- name: log-volume
emptyDir: {}
答案
1. 获取并编辑该 Pod(假设是以 YAML 文件管理)
kubectl get pod legacy-app -o yaml > legacy-app.yaml
2. 编辑 legacy-app.yaml,进行以下修改:
A. 添加一个共享卷,例如 log-volume:
volumes:
- name: log-volume
emptyDir: {}
B. 给原来的容器加挂载(如果已有就跳过):
containers:
- name: legacy-container # 你不能修改此容器的其它配置,只能添加 volumeMount
...
volumeMounts:
- name: log-volume
mountPath: /var/log
⚠️ 如果原来的容器已经挂载了 /var/log,就不要重复添加。
C. 添加 sidecar 容器配置:
- name: sidecar
image: busybox:stable
command: ["/bin/sh", "-c"]
args: ["tail -n+1 -f /var/log/legacy-app.log"]
volumeMounts:
- name: log-volume
mountPath: /var/log
3. 应用修改:
kubectl delete pod legacy-app
kubectl apply -f legacy-app.yaml
⚠️ 不能直接修改运行中的 Pod,必须删除并重建(因为 Pod 是不可变的)。
示例完整片段(重点部分)
apiVersion: v1
kind: Pod
metadata:
name: legacy-app
spec:
containers:
- name: legacy-container
image: legacy-image
volumeMounts:
- name: log-volume
mountPath: /var/log
- name: sidecar
image: busybox:stable
command: ["/bin/sh", "-c"]
args: ["tail -n+1 -f /var/log/legacy-app.log"]
volumeMounts:
- name: log-volume
mountPath: /var/log
volumes:
- name: log-volume
emptyDir: {}
4. 验证:kubectl logs legacy-app -c sidecar
官网参考:https://kubernetes.io/docs/concepts/workloads/pods/sidecar-containers/
application/deployment-sidecar.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:
app: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: alpine:latest
command: ['sh', '-c', 'while true; do echo "logging" >> /opt/logs.txt; sleep 1; done']
volumeMounts:
- name: data
mountPath: /opt
initContainers:
- name: logshipper
image: alpine:latest
restartPolicy: Always
command: ['sh', '-c', 'tail -F /opt/logs.txt']
volumeMounts:
- name: data
mountPath: /opt
volumes:
- name: data
emptyDir: {}
题目4 StorageClass
设置配置环境 kubectl config use-context k8s
Task
首先,为名为 hostpath.csi.k8s.io 的现有制备器,创建一个名为 local-path的新 StorageClass
将卷绑定模式设置为 WaitForFirstConsumer
注意,没有设置卷绑定模式,或者将其设置为 WaitForFirstConsumer 之外的其他任何模式,都将导致分数降低。
接下来,将 local-path StorageClass 配置为默认的 StorageClass
请勿修改任何现有的 Deployment 和 PersistentVolumeClaim,否则将导致分数降低。
任务要求整理
- 创建一个新的 StorageClass:名称:local-path
需要使用已有的 provisioner:hostpath.csi.k8s.io
设置 volumeBindingMode: WaitForFirstConsumer- 设置该 StorageClass 为默认的方式:通过设置 annotation
storageclass.kubernetes.io/is-default-class: “true”注意:
不要改动任何现有的 Deployment 或 PVC
如果未设置 WaitForFirstConsumer 会被扣分
设置其他绑定模式也会扣分
官网参考:
文档地址 依次点击 Concepts → Storage → Storage Classes → StorageClass objects
https://kubernetes.io/docs/concepts/storage/storage-classes/
答案:
annotations为“true”、volumeBindingMode 为 WaitForFirstConsumer
local-path-sc.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-path
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: hostpath.csi.k8s.io
reclaimPolicy: Retain # default value is Delete
allowVolumeExpansion: true
mountOptions:
- discard # this might enable UNMAP / TRIM at the block storage layer
volumeBindingMode: WaitForFirstConsumer
parameters:
guaranteedReadWriteLatency: "true" # provider-specific
应用以上资源
kubectl apply -f local-path-sc.yaml
检查 kubectl get sc,能看到刚创建的 sc 后面有 default 即可
kubectl get storageclass
题目5 service
设置配置环境 kubectl config use-context k8s
Task
- 重新配置 spline-reticulator namespace 中现有的 front-end Deployment,以公开现有容器 nginx 的端口 80/tcp
- 创建一个名为 front-end-svc 的新 Service ,以公开容器端口 80/tcp 配置新的 Service ,以通过 NodePort 公开各个 Pod
练习环境准备(考试无需此操作)
vim front-end.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: front-end
namespace: spline-reticulator
labels:
app: front-end
spec:
replicas: 1
selector:
matchLabels:
app: front-end
template:
metadata:
labels:
app: front-end
spec:
containers:
- name: nginx
image: docker.m.daocloud.io/library/nginx:latest
imagePullPolicy: IfNotPresent
答案
第一步:编辑现有的 Deployment,公开80端口
在线编辑
kubectl edit deploy front-end -n spline-reticulator
如果考试时,忘记了yaml格式,就查官方帮助文档,搜索关键字“Deployment”
ports:
- containerPort: 80
name: http
protocol: TCP
注意这里按空格键而不是 tab 进行缩进,edited之后,保存退出后会有提示(由内容改变就是edited,没有就是no changes)
通过服务发布出去:(记不住,查官网,搜索kubectl expose关键词)
第二步:暴露资源:kubectl expose
kubectl expose deploy front-end \
--name=front-end-svc \
--port=80 \
--target-port=80 \
--type=NodePort \
-n spline-reticulator
kubectl expose deploy front-end --name=front-end-svc -n spline-reticulator --port 80 --type NodePort
上图可以看出暴露出的端口是80:31566/TCP,可以通过ip访问这个端口
在 Kubernetes 中,NodePort 类型的 Service 并不绑定在某一个节点上运行,而是将端口暴露在集群中每个节点的 IP 上的指定端口上(NodePort)。所以这个 Service 可以在任意一个节点的 IP + NodePort 被访问。
题目6 Pod 优先级 PriorityClass
设置配置环境 kubectl config use-context k8s
Task请执行以下任务:
- 为用户工作负载创建一个名为 high-priority 的新 PriorityClass ,其值比用户定 义的现有最高优先级类值小一。
- 修改在 priority namespace 中运行的现有 busybox-logger Deployment ,以使用 high-priority 优先级类。
- 确保 busybox-logger Deployment 在设置了新优先级类后成功部署。
- 请勿修改在 priority namespace 中运行的其他 Deployment,否则可能导致分数 降低。
官网参考
依次点 击 Concepts → Scheduling, Preemption and Eviction → Pod Priority and Preemption → Example PriorityClass
https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/
答案
第一步:查看当前已有的 PriorityClass,找出用户自定义的最高值
查看优先级
kubectl get pc
其中 system-cluster-critical 和 system-node-critical 是集群默认带的,而有一个max-user-priority 是用户自定义的。
其值为 1000000000(十位数),所以小一就是九个 9(999999999)
第二步:创建一个新的 PriorityClass,值比最大用户定义的值小 1
创建pc,(忘记了创建命令,就使用“–help”)
kubectl create pc high-priority --value=999999999
创建练习环境(考试不用做)
cat busybox-logger-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: busybox-logger
namespace: priority
labels:
app: busybox-logger
spec:
replicas: 1
selector:
matchLabels:
app: busybox-logger
template:
metadata:
labels:
app: busybox-logger
spec:
containers:
- name: busybox
image: docker.m.daocloud.io/library/busybox
imagePullPolicy: IfNotPresent
args:
- /bin/sh
- -c
- while true; do echo $(date -u) >> /var/log/date.log; sleep 5; done
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
第三步:编辑 busybox-logger Deployment 添加 priorityClassName
编辑 deploy
kubectl edit deployment busybox-logger -n priority
我认为正确的做法
apiVersion: apps/v1
kind: Deployment
metadata:
name: busybox-logger
namespace: priority # 确保这是正确的命名空间
labels:
app: busybox-logger
spec:
replicas: 1
selector:
matchLabels:
app: busybox-logger
template:
metadata:
labels:
app: busybox-logger
spec:
priorityClassName: high-priority # 在这里添加优先级类名称
containers:
- name: busybox
image: busybox
args:
- /bin/sh
- -c
- while true; do echo $(date -u) >> /var/log/date.log; sleep 5; done
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
在 pod 的 spec 下添加(不是 deployment 的 spec)
priorityClassName: high-priority
(记得这个要比 spec 下缩进 2 个空格)
如果忘记priorityClassName怎么写,就查官网,在官网首页文档处搜索“priorityClass”关键词。
第四步:验证 Pod 是否使用了正确的 PriorityClass
验证:
kubectl get deployment busybox-logger -n priority
kubectl get pod -n priority | grep busybox-logger
查看priority这个pod下的优先级是否修改成功了。
以下是优先级设置成功的截图
题目7 argoCD
设置配置环境 kubectl config use-context k8s
文档 Argo Helm Charts (打开的连接是 https://argoproj.github.io/argo-helm/)
Task
通过执行以下任务在集群中安装 Argo CD:
- 添加名为 argo 的官方 Argo CD Helm 存储库。
注意:Argo CD CRD 已在集群中预安装。- 为 argocd namespace 生成 Argo CD Helm 图表版本 5.5.22 的模板,并将其保存到 ~/argo-helm.yaml ,将图表配置为不安装 crds 。
- 使用 Helm 安装 Argo CD ,并设置发布名称为 argocd ,使用与模板中相同的配置和版本(5.5.22) ,
- 将其安装在 argocd namespace 中,并配置为不安装 crds 。
注意:您不需要配置对 Argo CD 服务器 UI 的访问权限。
helm repo add argo-cn https://openchart.choerodon.com.cn/choerodon/argo
题目文档里给的连接是 https://argoproj.github.io/argo-helm/
因为网络问题,练习环境里可以先给添加好了,练习时不用自己做了,考试要自己做
要想自己添加,可以先删除
helm repo remove argo
导出模板的语法 (记不住查帮助:helm template --help)
helm template 的语法是
helm template [NAME] [CHART] [flags]
题目要求安装应用的名字为 argocd,这里模板的名字保持和他一样
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
helm repo list
kubectl create ns argocd
答案
第一步:添加 Helm 仓库
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
添加完之后可以通过argo这个name名来search相关内容
验证 chart 是否存在版本 5.5.22:
helm search repo argo/argo-cd --versions | grep 5.5.22
第二步:生成 Argo CD Helm 图表版本 5.5.22 的模板
生成模板文件 argo-helm.yaml
helm template argocd argo/argo-cd \
--version 5.5.22 \
-n argocd \
--set crds.install=false > ~/argo-helm.yaml
第三步:使用 Helm 安装 Argo CD
安装
可以通过以下命令,查看安装操作时argo/argo-cd这个参数
helm install argocd argo/argo-cd \
--version 5.5.22 \
-n argocd \
--set crds.install=false
检查 Helm release 是否部署成功
之后执行
kubectl get pods -n argocd
看这里的 pod,让他自己运行即可,不用等,继续做后面的题目。
步骤命令总结
# 添加 Helm 仓库
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
# 创建命名空间
kubectl create namespace argocd
# 生成模板 YAML,跳过 CRD
helm template argocd argo/argo-cd \
--version 5.5.22 \
-n argocd \
--skip-crds \
> ~/argo-helm.yaml
# 安装 Helm Chart,跳过 CRD
helm install argocd argo/argo-cd \
--version 5.5.22 \
-n argocd \
--skip-crds
解释:
argocd:release 名称
argo/argo-cd:chart 名称
–skip-crds:跳过 crd 渲染
–version 5.5.22:指定版本
–namespace argocd:指定命名空间
~/argo-helm.yaml:输出为模板 YAML 文件
题目8 PVC
设置配置环境 kubectl config use-context k8s
Task
mariadb namespace 中的 MariaDB Deployment 被误删除。请恢复该 Deployment 并确保数据持久性。请按照以下步骤:
如下规格在 mariadb namespace 中创建名为 mariadb 的 PersistentVolumeClaim
(PVC):访问模式为 ReadWriteOnce
存储为 250Mi
集群中现有一个 PersistentVolume。
您必须使用现有的 PersistentVolume (PV)。
编辑位于 ~/mariadb-deployment.yaml 的 MariaDB Deployment 文件,以使用上一步中创建的 PVC。
将更新的 Deployment 文件应用到集群。
确保 mariadb Deployment 正在运行且稳定。
查看storageclass
文件内容如下:
vim mariadb-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mariadb
namespace: mariadb
spec:
replicas: 1
selector:
matchLabels:
app: mariadb
template:
metadata:
labels:
app: mariadb
spec:
containers:
- name: mariadb
image: docker.m.daocloud.io/library/mariadb:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mariadb
创建pv(考试不用做,会自动创建)
vim pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: mariadb-pv
spec:
capacity:
storage: 250Mi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: slow
claimRef:
kind: PersistentVolumeClaim
namespace: mariadb
name: mariadb
hostPath:
path: /mnt/data/mariadb
答案:
第一步:先查看PV:kubectl get pv
执行 kubectl get pv,查看 STORAGECLASS 那列的值,这里为 SLOW,考试时看清具体的值(此值pvc需和pv保持一致)。
第二步:创建PVC
创建文件 8-pvc.yaml (资源不会写可以查官网模板)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mariadb
namespace: mariadb
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 250Mi
storageClassName: slow
官网模板:
https://kubernetes.io/docs/concepts/storage/persistent-volumes/
创建 pvc 资源
kubectl apply -f 8-pvc.yaml -n mariadb
验证是否关联在一起了
kubectl get pvc
此时pv和pvc已经通过slow这个storageclass绑定(Bound)在一起了。
题目9 gateway
设置配置环境 kubectl config use-context k8s
Task
将现有 Web 应用程序从 Ingress 迁移到 Gateway API。您必须维护 HTTPS 访问权限。
- 注意:集群中安装了一个名为 nginx 的 GatewayClass 。
- 首先,创建一个名为 web-gateway 的 Gateway ,主机名为gateway.web.k8s.local ,并保持现有名为 web 的 Ingress 资源的现有 TLS 和侦听器配置。
- 接下来,创建一个名为 web-route 的 HTTPRoute ,主机名为gateway.web.k8s.local ,并保持现有名为 web 的 Ingress 资源的现有路由规则。
- 您可以使用以下命令测试 Gateway API 配置: url -Lk https://gateway.web.k8s.local:31144
- 最后,删除名为 web 的现有 Ingress 资源。
答案:(只做gateway的)
第一步:先查名为 web 的 ingress 的属性,找到secretName
查看已有 Ingress 的配置:
kubectl get ingress web -o yaml # ing是ingress的缩写
重点查看:
host: gateway.web.k8s.local
tls.secretName: 比如是 web-cert
backend service: 比如是 web:80
ingress 的名字为 web,先查询这个名字为 web 的 ingress 的属性 ,kubectl get ing web -o yaml, 在最后几行能看到用到的 secret 名字
假设 web 的 Service此时服务通过 ingress 已经发布出去,能够正常访问,还要找到所使用服务的名字创建网关。
查看是否存在 Secret(TLS 证书):
kubectl get secret web-cert -n default
第二步:创建 Gateway.yaml
文档地址:
Concepts → Services, Load Balancing, and Networking → Gateway API → Gateway 和
Concepts → Services, Load Balancing, and Networking → Gateway API → HTTPRoute
https://kubernetes.io/docs/concepts/services-networking/gateway/
这里的 yaml 地址需要参考文档然后修改,下面 tls 及下面的 3 行加黑部分记住它。
tls:
certificateRefs:
- name: web-cert
或者通过 kubectl explain gtw.spec | grep list,知道 listeners 的拼写,然后继续下面的命令
kubectl explain gtw.spec.listeners.tls
kubectl explain gtw.spec.listeners.tls.certificateRefs
逐步查看出来,创建:gtw.yaml
cat 9-gtw.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: web-gateway
spec:
gatewayClassName: nginx
listeners:
- name: foo-https
protocol: HTTPS
port: 443
hostname: gateway.web.k8s.local
tls:
certificateRefs:
- name: web-cert
kubectl apply -f 9-gtw.yaml
kubectl get gtw
第三步:创建 HTTPRoute.yaml
建立 httproute
这个就从官网复制,并修改 httproute.yaml
cat 9-httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web-route
spec:
parentRefs:
- name: web-gateway
hostnames:
- "gateway.web.k8s.local"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: web
port: 80
练习的是时候需要添加,ip替换为node的地址
#/etc/hosts
192.168.10.22 gateway.web.k8s.local
kubectl apply -f 9-httproute.yaml
kubectl get httproutes
第四步:验证是否生效
curl -k https://gateway.web.k8s.local:31144
最后:删除旧的 Ingress 资源
删除 ingress
kubectl delete ingress web -n default
题目10 网络策略
设置配置环境 kubectl config use-context k8s
Task
从提供的 YAML 样本中查看并应用适当的 NetworkPolicy。
- 确保选择的 NetworkPolicy 不过于宽松,同时允许运行在 frontend 和 backend namespaces 中的 frontend 和 backend Deployment 之间的通信。
- 首先,分析 frontend 和 backend Deployment,以确定需要应用的NetworkPolicy的具体要求。
- 接下来,检查位于 ~/netpol 文件夹中的 NetworkPolicy YAML 示例。
注意:
- 请勿删除或修改提供的示例。仅应用其中一个。否则可能会导致分数降低。最后,应用启用 frontend 和 backend Deployment 之间的通信的 NetworkPolicy,但不要过于宽容。
- 注意:请勿删除或修改现有的默认拒绝所有入站流量或出口流量NetworkPolicy。否则可能导致零分。
答案:
- 查看~/netpol 里几个策略的内容
- 第一个文件是允许命名空间 frontend 里所有的 pod 都能访问
- 第二个策略:允许 frontend namespace 下有 app=frontend 标签的 Pod,访问 backend namespace 下有 app=backend 标签的 Pod。
- 第二个比第一个策略更合适,第一个开放的范围太多了。
- 第三个策略:看到 backend namespace 下有 app=database 标签的 Pod,就不用 看了。这个显然是错误的,backend namespace 下的 Pod,标签是app=backend,而不是 app=database
所以,最终选择 netpol2.yaml 创建
kubectl apply -f ~/netpol/netpol2.yaml
答案
① 查看 frontend 和 backend 的部署信息
kubectl get deploy -n frontend
kubectl get deploy -n backend
kubectl get pods -n frontend -o wide
kubectl get pods -n backend -o wide
你要知道 frontend 和 backend 的 Pod 是否通过 label 选择器识别,比如:
labels:
app: frontend
② 查看 frontend 是否需要访问 backend
你需要确认是:
frontend → backend:需要放通
backend → frontend:不需要放通(通常情况)
③ 查看 ~/netpol 目录下的 YAML 示例
ls ~/netpol
依次查看文件内容:
cat ~/netpol/policy-1.yaml
cat ~/netpol/policy-2.yaml
...
找到那个允许 frontend namespace 的 Pod 访问 backend namespace 的 Pod,且其他不放通的策略。
🎯 理想策略具备以下特征:
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: backend
spec:
podSelector: {} # 作用于 backend 中所有 pod
ingress:
- from:
- namespaceSelector:
matchLabels:
name: frontend
ports:
- port: 80
⚠️ 注意:
不能用 from: [{}] 这样宽松的配置;
不应该放通所有命名空间;
不应该添加出口规则(除非明确要求);
不能删除已有的 default deny 策略。
④ 应用最合适的 NetworkPolicy
确认选择后:
kubectl apply -f ~/netpol/policy-X.yaml
⑤ 验证(可选)
你可以测试 frontend pod 是否可以访问 backend pod:
kubectl exec -n frontend <frontend-pod> -- curl <backend-service>:<port>
题目11 自定义资源 CRD
设置配置环境 kubectl config use-context k8s
Task
验证已部署到集群的 cert-manager 应用程序。
- 使用 kubectl ,将 cert-manager 所有定制资源定义(CRD)的列表,保存到 ~/resources.yaml 。
注意:您必须使用 kubectl 的默认输出格式。请勿设置输出格式。否则将导致分 数降低。- 使用 kubectl ,提取定制资源 Certificate 的 subject 规范字段的文档,并将其保存到 ~/subject.yaml 。
注意:您可以使用 kubectl 支持的任何输出格式。如果不确定,请使用默认输出 格式。
准备练习环境,安装 cert-manager(考试不用做)
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.13.3 \
--set installCRDs=true
答案
1. 先查看 cert-manager 里的pod正常运行
kubectl get pods -n cert-manager
2. 然后找到 cert-manager 相关的 crd
kubectl get crd | grep cert-manager
或
kubectl get crd -l app.kubernates.io/name=cert-manager
3. 保存内容: kubectl get crd | grep cert-manager > ~/resources.yaml
保存到指定的文件
kubectl get crd | grep cert-manager > ~/resources.yaml
或
kubectl get crd -l app.kubernetes.io/name=cert-manager > ~/resources.yaml
4. 保存内容:kubectl explain certificate.spec.subject > ~/subject.yaml
找到题目要求的字段,保存到指定的文件
kubectl explain certificate.spec.subject > ~/subject.yaml
kubectl explain certificate.spec.subject
如何一步步查字段路径?
你可以用 kubectl explain 逐级展开,比如:
kubectl explain certificate # 查看顶层字段,确认有spec
kubectl explain certificate.spec # 查看spec下的字段,有subject
kubectl explain certificate.spec.subject
题目12 configmap
设置配置环境 kubectl config use-context k8s
Task
名为 nginx-static 的 NGINX Deployment 正在 nginx-static namespace 中运行。
它通过名为 nginx-config 的 ConfigMap 进行配置。
更新 nginx-config ConfigMap 以仅允许 TLSv1.3 连接。
注意:您可以根据需要重新创建、重新启动或扩展资源。
您可以使用以下命令测试更改:
curl -k --tls-max 1.2 https://web.k8snginx.local
练习环境准备(考试不需要做)
vim nginx-tls12.yaml
apiVersion: v1
kind: Namespace
metadata:
name: nginx-static
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
namespace: nginx-static
data:
nginx.conf: |
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
sendfile on;
keepalive_timeout 65;
gzip on;
server {
listen 80;
server_name localhost;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name web.k8snginx.local;
ssl_certificate /etc/nginx/ssl/tls.crt;
ssl_certificate_key /etc/nginx/ssl/tls.key;
# 只允许 TLSv1.2
ssl_protocols TLSv1.2;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ =404;
}
}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-static
namespace: nginx-static
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: docker.m.daocloud.io/library/nginx:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
- containerPort: 443
volumeMounts:
- name: nginx-config-volume
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
- name: tls-certs
mountPath: /etc/nginx/ssl
volumes:
- name: nginx-config-volume
configMap:
name: nginx-config
- name: tls-certs
secret:
secretName: nginx-tls
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: nginx-static
spec:
type: NodePort
selector:
app: nginx
ports:
- protocol: TCP
port: 443
targetPort: 443
nodePort: 30443
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt -subj "/CN=web.k8snginx.local"
kubectl create secret tls nginx-tls \
--cert=tls.crt \
--key=tls.key \
-n nginx-static
echo "10.100.68.202 web.k8snginx.local" | sudo tee -a /etc/hosts
启动成功后,可以通过nodeport的端口访问这个nginx服务
root@dev-master:~# kubectl exec -it nginx-static-75f8dfb7dc-zrbtx -nnginx-static bash
cd /etc/nginx/conf.d
/etc/nginx/conf.d# mv default.conf default.conf_bak
nginx -s reload
curl -k --tls-max 1.2 https://web.k8snginx.local
答案
第一步:先测试 :curl -k --tls-max 1.2
curl -k --tls-max 1.2 https://web.k8snginx.local
第二步:先备份后修改:kubectl edit configmap
建议备份一份
kubectl get configmaps nginx-config -n nginx-static
kubectl get configmap nginx-config -n nginx-static -o yaml > nginx-config.yaml
然后再修改
kubectl edit configmap -n nginx-static nginx-config
第三步:删除:TLSv1.2
删除里面的 TLSv1.2,按 esc,保存退出 重启 deployment
第四步:滚动更新测试:kubectl rollout restart
kubectl rollout restart deployment nginx-static -n nginx-static
之后测试
curl -k --tls-max 1.3 https://web.k8snginx.local
curl -k --tls-max 1.2 https://web.k8snginx.local
题目13 calico
设置配置环境 kubectl config use-context k8s
文档地址
Flannel Manifest :https://github.com/flannel-io/flannel/releases/download/v0.26.1/kube-flannel.yml
Calico Manifest :https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/tigera-operator.yaml
集群的 CNI 未通过安全审核,已被移除。您必须安装一个可以实施网络策略的 新 CNI。
Task安装并设置满足以下要求的容器网络接口(CNI):
选择并安装以下 CNI 选项之一:
Flannel 版本 0.26.1
Calico 版本 3.28.2
选择的 CNI 必须:
让 Pod 相互通信
支持 Network Policy 实施
从清单文件安装(请勿使用 Helm)
答案
第一步:下载并编辑官方提供的 tigera-operator.yaml
因为题目要求支持 Network Policy 实施,而 Flannel 其实不支持 Network Policy,所以只能选择支持的 Calico 部署。
下载 tigera-operator
wget https://raw.githubusercontent.com/projectcalico/calico/v3.28.2/manifests/tigera-operator.yaml
部署 tigera-operator 必须使用 kubectl create 而非 apply。
直接使用 apply 可能导致 CRD 冲突。
kubectl create -f tigera-operator.yaml
查看集群的 cidr 地址,一般默认
kubectl cluster-info dump | grep -i cidr (clusterIP)
都是 10.244.0.0/16,但是这里还是要去查一下。
第二步:安装 Calico CRD(CustomResource)
下载 CRD
这个网址题目没有给你,其实就是将上一步网址中的 tigera-operator.yaml 改成 custom-resources.yaml,所以这个单词一定要背过。
wget https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/custom-resources.yaml
注意后面的yaml文件名称“custom-resources”是和前面下载的不同地方,把他记住。 这个文件的内容很少,修改里面的 cidr,修改成前面查到的。
然后运行
kubectl create -f custom-resources.yaml
第三步:确认安装成功,确保 calico-node DaemonSet 运行中:
kubectl get pods -n kube-system -l k8s-app=calico-node
如何查看某个 Pod 的标签?
题目14 resources cpu 和 memory
考察:设置合理的 CPU 和内存请求,并确保资源公平分配且 Pod 可正常运行
设置配置环境 kubectl config use-context k8s
Context
您管理一个 WordPress 应用程序。由于资源请求过高,某些 Pod 无法启动。
Task
relative-fawn namespace 中的 WordPress 应用程序包含:
- 具有 3 个副本的 WordPress Deployment
- 按如下方式调整所有 Pod 资源请求:
- 将节点资源平均分配给这 3 个 Pod
- 为每个 Pod 分配公平的 CPU 和内存份额
- 添加足够的开销以保持节点稳定
- 请确保,对容器和初始化容器使用完全相同的请求。
- 您无需更改任何资源限制。
- 在更新资源请求时,暂时将 WordPress Deployment 缩放为 0 个副本可能会有所帮助。
更新后,请确认:
WordPress 保持 3 个副本
所有 Pod 都在运行并准备就绪
答案
将 WordPress Deployment 缩放为 0 个副本
题目里明确指明,要先将 Deployment 缩放为 0。
考试时,如果不将其缩小为 0,而是直接修改 cpu 和 memory 值,会导致新 Pod 起不来,因为考试环境提前做了一些限制。
kubectl scale deployment wordpress -n relative-fawn --replicas=0
检查 nodes 资源请求情况
考试只有一个 node 节点,模拟环境里,我们假设是 vms22.rhce.cc这个 node 节点即可。
要先缩为 0 后,再检查 node 资源请求情况。
kubectl get nodes
kubectl describe node vms22.rhce.cc
CPU 550m 占用了 27%,可计算出大约每 1%是 20m。
- 因为当前已经申请用了 27%,所以还剩下 73%可供申请,也就是一共还剩 1460m 可以申请。(20m*73)
- 然后,这个 deployment 是里面有 2 个 containers 容器(含一个初始化容器),
而且最终是要 3 副本,所以一共有 6 个 containers 平分 1460m,每个containers 约可以分 243m(1460m 被 6 个容器分,即 1460/6)。- 所以每个 containers 的 cpu requests 上限不能超过 243m,所以理论上 cpu request :1m-243m 都可以设置。
这里就设置 100m ,因为太低了,可能也会导致 Pod 获取不到资源。- 同样的方法,memory request 360Mi 占 9%,所以大于每 1%为 40Mi。 剩余 91%可供申请,也就是剩余 3640Mi。
让 6 个 containers 平分,所以每个最高是 606Mi。 这里就设置为 200Mi 。如果不会计算的话,只需要记住考试时,
- 这道题 requests cpu 也是设置为 100m,
- requests memory 也是设置为 200Mi,就可以保证 Pod 正常 Running。
因为考试做了一些隐形限制,如果 request 过低或者过高,都会让 Pod 无法启动。
kubectl scale deployment wordpress -n relative-fawn --replicas=3
答案
第一步:先缩容副本数为 0
kubectl scale deployment wordpress -n relative-fawn --replicas=0
第二步:修改 Deployment 资源(包括容器和 init 容器 requests)
#推荐设置:每个容器 cpu request: 100m
#推荐设置:每个容器 memory request: 200Mi
kubectl edit deployment wordpress -n relative-fawn
找到 spec.template.spec.containers 和 initContainers 部分,在每个容器中添加以下内容:
#注意看是否有如下两个设置一样的值
containers:
- name: wordpress
resources:
requests:
cpu: 100m
memory: 200Mi
initContainers:
- name: init-wordpress
resources:
requests:
cpu: 100m
memory: 200Mi
上面步骤不要改动 limits 的部分,只改 requests!
(如果忘记了怎么写,可以在官方文档中搜索“resources”关键字)
官方帮助文档:https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
第三步:恢复副本数为 3
kubectl scale deployment wordpress -n relative-fawn --replicas=3
#检查pod
kubectl get pods -n relative-fawn -w
题目15 etcd 修复
排查并修复单节点集群在迁移后失效的原因
设置配置环境 kubectl config use-context k8s
Context
kubeadm 配置的集群已迁移到新机器。它需要更改配置才能成功运行。
Task
修复在机器迁移过程中损坏的单节点集群。首先,确定损坏的集群组件,并调查导致其损坏的原因。
注意:已停用的集群使用外部 etcd 服务器。
接下来,修复所有损坏的集群组件的配置。
注意:确保重新启动所有必要的服务和组件,以使更改生效。否则可能导致分数降低。
最后,确保集群运行正常。确保: 每个节点 和 所有 Pod 都处于 Ready 状态。
答案
修改两个文件
第一个文件:/etc/kubernetes/manifests/kube-apiserver.yaml
vim /etc/kubernetes/manifests/kube-apiserver.yaml
这个地址改成 127.0.0.1
第二个文件:/etc/kubernetes/manifests/kube-scheduler.yaml
vim /etc/kubernetes/manifests/kube-scheduler.yaml
这里的 cpu 的值由 4 改为 100m,整个文件里就这一处 CPU。
重启服务 systemctl restart kubelet
systemctl restart kubelet
kubectl get nodes
题目16 cri-dockerd
关于 为 Kubernetes 使用 cri-dockerd 做节点准备 的题型
设置配置环境 kubectl config use-context k8s
Context
您的任务是为 Kubernetes 准备一个 Linux 系统。 Docker 已被安装,但您需要为 kubeadm 配置它。
Task
完成以下任务,为 Kubernetes 准备系统:
- 设置 cri-dockerd :
- 安装 Debian 软件包 ~/cri-dockerd_0.3.6.3-0.ubuntu-jammy_amd64.deb
Debian 软件包使用 dpkg 安装。- 启用并启动 cri-docker 服务
- 配置以下系统参数:
- net.bridge.bridge-nf-call-iptables 设置为 1
net.ipv6.conf.all.forwarding 设置为 1
net.ipv4.ip_forward 设置为 1
net.netfilter.nf_conntrack_max 设置为 131072
确保这些系统参数在系统重启后仍然存在,并应用于正在运行的系统。
答案
第一步:安装软件包 sudo dpkg -i
sudo dpkg -i ~/cri-dockerd_0.3.6.3-0.ubuntu-jammy_amd64.deb
第二步:启用服务:systemctl enable cri-docker
启动服务
sudo systemctl enable cri-docker
第三步:配置系统参数 /etc/sysctl.conf
配置题目要求的参数
修改配置文件
sudo vim /etc/sysctl.conf
在最后面添加如下参数
net.bridge.bridge-nf-call-iptables=1
net.ipv6.conf.all.forwarding=1
net.ipv4.ip_forward=1
net.netfilter.nf_conntrack_max=131072
第四步:生效配置:sysctl -p /etc/sysctl.conf
保存退出之后,按如下命令让参数生效
sudo sysctl -p /etc/sysctl.conf