K8S应用笔记
K8S资源
-
Namespace(命名空间):
k8s通过命名空间实现资源隔离, 简称为ns
我们在获取任何资源时,如果不明确指定命名空间那么会缺省的使用default命名空间
-
Pod:
K8s的最小运行单元(不太恰当的比喻,一个pod就详单与用docker启动了一个容器)
-
Controller(控制器):
一般来说生产环境都是通过各种Controller来管理pod的生命周期。在控制器中每一个副本都是一个pod 通过控制副本数来控制pod的创建和销毁
常用的Controller有Deployment、DaemonSet、StatefulSet、Job、CronJob
最常用的是 Deployment(无状态应用)
-
replicas:副本数
Deployment通过replicas属性来指定副本数 简称rs
-
service: 不论单独创建的pod 还是通过deployment创建的pod 都是一个在k8s集群中的资源,他们的访问只能通过集群内ip访问,不能通过外网访问 所以需要通过service来暴露pod访问
service常用的四种网络
- ClusterIP:集群内部访问,分配了一个稳定的虚拟ip。
- NodePort:集群外部访问,会在每个node节点上分配固定的端口(端口范围30000-32767),流量可以从外部转发到service,
- LoadBalancer:集群外部访问,主要在云环境中使用。他为service创建一个外部的负载均衡器,可以通过云环境的负载均衡器将流量打到service上
- ExternalName:通过返回一个CNAME记录,可以将服务映射到集群外部的服务。
-
endpoints(v1 Endpoints is deprecated in v1.33+; use discovery.k8s.io/v1 EndpointSlice): 1.33以后被弃用
-
EndpointSlice: 用于描述Service的实际访问点。它包含了提供服务的Pod的IP地址和端口信息。
这些信息是Kubernetes实现服务发现和流量分发的关键依据
增(创建)
-
新增命名空间
kubectl create ns ${nsName} #新建一个deployment # 应用名 镜像地址 副本数 -
创建(运行)一个pod
kubectl run ${podName} --image=${镜像名称}:${镜像tag} -
心中一个deployment 应用
kubectl create deployment ${deploymentName} --image=${镜像名称}:${镜像tag} --replicas=${副本数} -
创建一个deployment的配置文件
kubectl create deployment nginx --image=nginx --dry-run=client -o yaml > nginx.yamlapiVersion: apps/v1 # 资源类型 kind: Deployment # 元数据,其中name是必填项 metadata: creationTimestamp: null labels: app: nginx name: nginx # 规格说明 spec: # 副本数 replicas: 1 selector: matchLabels: app: nginx strategy: {} # 定义 Pod 的模板,这是配置文件的重要部分 template: # metadata 定义 Pod 的元数据,至少要定义一个 label。label 的 key 和 value 可以任意指定 metadata: creationTimestamp: null labels: app: nginx # spec 描述 Pod 的规格,此部分定义 Pod 中每一个容器的属性,name 和 image 是必需的 spec: containers: - image: nginx name: nginx resources: {} status: {} -
创建一个service (svc)
# 创建一个新的service, 将流量从端口5000 映射到 pod 80 端口 kubectl create service clusterip new-nginx --tcp=5000:80 # 基于一个已存在的(名为new-nginx的)deployment 创建一个svc 网络模式为NodePort --port 是svc对外端口 kubectl expose deployment new-nginx --type=NodePort --port=81 --target-port=80 --dry-run=client -o yaml > nginx-svc.yamlapiVersion: v1 # <<<<<< v1 是 Service 的 apiVersion kind: Service # <<<<<< 指明当前资源的类型为 Service metadata: creationTimestamp: null labels: app: new-nginx name: new-nginx # <<<<<< Service 的名字为 nginx spec: ports: - port: 81 # <<<<<< 将 Service 的 80 端口映射到 Pod 的 80 端口,使用 TCP 协议 protocol: TCP targetPort: 80 selector: app: new-nginx # <<<<<< selector 指明挑选那些 label 为 run: nginx 的 Pod 作为 Service 的后端 status: loadBalancer: {} -
给命名空间添加tls证书
kubectl -n <namespace> create secret tls boge-com-tls(这相当于证书的名称) --key boge.key(私钥路径) --cert boge.csr(证书路径)
删
-
通用表达式
# 删除资源时 资源类型和名称必填 kubectl delete ${资源类型} ${资源名称}
删除命名空间时,命名空间一直terminating
deleteK8sNamespace() {
set -eo pipefail
die() { echo "$*" 1>&2 ; exit 1; }
need() {
which "$1" &>/dev/null || die "Binary '$1' is missing but required"
}
# checking pre-reqs
need "jq"
need "curl"
need "kubectl"
PROJECT="$1"
shift
test -n "$PROJECT" || die "Missing arguments: kill-ns <namespace>"
kubectl proxy &>/dev/null &
PROXY_PID=$!
killproxy () {
kill $PROXY_PID
}
trap killproxy EXIT
sleep 1 # give the proxy a second
kubectl get namespace "$PROJECT" -o json | jq 'del(.spec.finalizers[] | select("kubernetes"))' | curl -s -k -H "Content-Type: application/json" -X PUT -o /dev/null --data-binary @- http://localhost:8001/api/v1/namespaces/$PROJECT/finalize && echo "Killed namespace: $PROJECT"
}
deleteK8sNamespace 要被删除的命名空间
改
-
修改deployment pod 的副本数
kubectl scale deployment nginx --replicas=2 -
修改deployment 镜像地址
root@k8s-192-168-0-17:/home/node1# kubectl get deployment -o wide NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR nginx 2/2 2 2 11m nginx docker.io/library/nginx:1.25.1 app=nginx # ${deploymentName}值得是上面结果中NAME列 ${containerName}为CONTAINERS列的值 kubectl set image deployments/${deploymentName} ${containerName}=${镜像地址}:${镜像版本} # 所以本次修改镜像的命令为 # 原来 kubectl set image ...... --replicas (--replicas 标志在 Kubernetes v1.18.0 后已弃用) # 1. 先修改镜像 kubectl set image deployments/nginx nginx=nginx:1.21.6 # 2. 再添加注释 kubectl annotate deployment/nginx kubernetes.io/change-cause="image updated to 1.21.6" -
回滚
# 1. 先查询发布历史 kubectl rollout history deployment ${deploymentName} deployment.apps/nginx REVISION CHANGE-CAUSE 1 <none> 2 image updated to 1.25.1 3 image updated to 1.21.6 # 2. 根据历史索引进行回滚 kubectl rollout undo deployment ${deploymentName} --to-revision=2 -
修改svc的网络模式
kubectl patch svc ${svcName} -p '{"spec":{"type":"NodePort"}}' -
给节点打标签(label)
#kubectl label node 10.0.1.201 apps/nginx=true kubectl label node ${nodeName} ${labelName}=${labelValue} kubectl label ${资源名称} ${nodeName} ${labelName}=${labelValue} -
给节点删除一个标签(Label)
kubectl label node ${nodeName} ${labelName}-
查
-
返回一种资源类型列表
## 返回一种资源类型列表,资源名称选填 ## 除了查询命名空间意外,其他资源类型都可以添加 -n 参数指定命名空间。 kubectl (-n ${nsName}) get ${资源类型} (${资源名称}) -o wide -
返回多种资源类型列表
kubectl (-n ${nsName}) get ${资源类型},${资源类型} -o widekubectl describe ${资源类型} ${资源名称}
-
进入到某个pod容器内
kubectl -it exec ${podName} -- bash(一般用bash|sh,也可以执行其他命令) -
查看当前某种资源的yaml
sudo kubectl get ${资源类型} ${资源名称} -o yaml -
查看标签(label)
kubectl get node ${nodeName} --show-labels -
查看集群的证书
健康检查
当容器退出时返回码非0 则认为容器发生了故障,k8s会根据restartPolicy策略来执行后续操作
restartPolicy的美剧
Always:总是重启 OnFailure:容器退出时返回码非0,则重启 Never:不重启
k8s的pod可以通过 Liveness 和 Readiness 来检查pod是否健康
-
通过Liveness进行健康检查
apiVersion: v1 kind: Pod metadata: labels: test: liveness name: liveness spec: restartPolicy: OnFailure containers: - name: liveness image: registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 # 容器启动后立即创建/tmp/healthy 文件,30s后 删除 args: - /bin/sh - -c - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600 livenessProbe: exec: command: - cat - /tmp/healthy # 容器启动 10 秒后开始检测 initialDelaySeconds: 10 # 容器启动 10 秒之后开始检测 # 每5s检查执行一次 cat /tmp/healthy periodSeconds: 5 # 每隔 5 秒再检测一次 -
通过Readiness进行健康检查
我们可以通过Readiness检测来告诉K8s什么时候可以将pod加入到服务Service的负载均衡池中,对外提供服务,这个在生产场景服务发布新版本时非常重要,当我们上线的新版本发生程序错误时,Readiness会通过检测发布,从而不导入流量到pod内,将服务的故障控制在内部,在生产场景中,建议这个是必加的,Liveness不加都可以,因为有时候我们需要保留服务出错的现场来查询日志,定位问题,告之开发来修复程序。
Liveness 检测和 Readiness 检测是两种 Health Check 机制,如果不特意配置,Kubernetes 将对两种检测采取相同的默认行为,即通过判断容器启动进程的返回值是否为零来判断检测是否成功。
两种检测的配置方法完全一样,支持的配置参数也一样。
不同之处在于检测失败后的行为:Liveness 检测是重启容器;Readiness 检测则是将容器设置为不可用,不接收 Service 转发的请求。
Liveness 检测和 Readiness 检测是独立执行的,二者之间没有依赖,所以可以单独使用,也可以同时使用。
用 Liveness 检测判断容器是否需要重启以实现自愈;用 Readiness 检测判断容器是否已经准备好对外提供服务。
Readiness 检测的配置语法与 Liveness 检测完全一样
apiVersion: v1 kind: Pod metadata: labels: test: readiness name: readiness spec: restartPolicy: OnFailure containers: - name: readiness image: registry.cn-hangzhou.aliyuncs.com/acs/busybox:v1.29.2 args: - /bin/sh - -c - touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600 readinessProbe: # 这里将livenessProbe换成readinessProbe即可,其它配置都一样 exec: command: - cat - /tmp/healthy #initialDelaySeconds: 10 # 容器启动 10 秒之后开始检测 periodSeconds: 5 # 每隔 5 秒再检测一次 startupProbe: # 启动探针,更灵活,完美代替initialDelaySeconds强制等待时间配置,启动时每3秒检测一次,一共检测100次 exec: command: - cat - /tmp/healthy failureThreshold: 100 periodSeconds: 3 timeoutSeconds: 1
部署一个生产环境下的Ingress-Nginx 控制器
必看:
-
在大规模生产集群上,ingree-nginx 独占一台节点,他就只跑 ingree-nginx 不要再跑其他pod了
-
kind: ConfigMap 段落的data.worker-processes = 实际服务器ingress-nginx-controller 所在的pod的那个节点的服务器的cpu核数(最好比实际核心数-1)
-
kind: ConfigMap 段落的data.worker-cpu-affinity 目前配置是空, 留空就行
-
kind: DaemonSet 如果是自建集群使用DaemonSet类型的控制器。 他会把容器端口映射到宿主机上这样就不用再使用NodePort映射了如果是是云上比如阿里云的ack 集群,使用Deployment类型的控制器,因为ack的pod使用的是云主机的弹性网卡他可以和你的云主机在同一个网络(网段)所以在这一段的内容中默认用了kind: DaemonSet 如果要用kind: Deployment 那么需要检查 “Deployment need” 和 “DaemonSet need"跟随的一些配置项
-
基于kind: DaemonSet|Deployment的resources(资源配置)如果limits分配的资源和requests分配的资源是一致的,那么这个pod在k8s集群中的优先级是最高的。当我们集群资源不够时, k8s会驱逐一些优先级低的pod。保证高优先级
-
如果日志报错提示 “mount: mounting rw on /proc/sys failed: Permission denied”, 那么就打开 privileged: true、procMount: Default、runAsUser: 0 这三条注释的内容,如果不报错就不用管他
-
给对应节点打标签
nodeSelector:
boge/ingress-controller-ready: "true"
打标签的方法 kubectl label node ${节点的hostname} boge/ingress-controller-ready=true
查看标签的方法 kubectl get node –show-labels
删除标签的方法 kubectl label node ${节点的hostname} boge/ingress-controller-ready-
- 基于ingress-nginx独立一台节点部署的情况。
给这个节点打上标签后。最好再给这个节点标记上污点
打污点的方法是 kubectl taint nodes xx.xx.xx.xx boge/ingress-controller-ready=“true”:NoExecute
去掉污点的方法是 kubectl taint nodes xx.xx.xx.xx boge/ingress-controller-ready:NoExecute-
如果给节点打上了污点需要把下面这段注释打开,
tolerations:
- effect: NoExecute # effect: NoExecute:表示节点污点的驱逐效果,会驱逐已运行但不耐受的Pod
key: boge/ingress-controller-ready
operator: Equal # 要求value必须完全匹配(若为Exists则只需key存在)
value: "true"
他的作用是Kubernetes中Pod的容忍度(Toleration)定义,用于控制Pod能否调度到带有特定污点(Taint)的节点上
所以上面这段的配置含义是
- 允许Pod被调度到带有boge/ingress-controller-ready=true:NoExecute污点的节点上,确保它们只运行在特定节点。