一、Kubernetes 是什么?
Kubernetes (K8S) 是由Google设计的用于自动化部署、大规模可伸缩、管理容器化应用程序的开源的容器编排引擎,目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。
传统的应用部署方式是通过插件或脚本来安装应用。这样做的缺点是应用的运行、配置、管理、所有生存周期将与当前操作系统绑定,这样做并不利于应用的升级更新/回滚等操作,当然也可以通过创建虚拟机的方式来实现某些功能,但是虚拟机非常重,并不利于可移植性。
新的方式是通过部署容器方式实现,每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。相对于虚拟机,容器能快速部署,由于容器与底层设施、机器文件系统解耦的,所以它能在不同云、不同版本操作系统间进行迁移。
容器占用资源少、部署快,每个应用可以被打包成一个容器镜像,每个应用与容器间成一对一关系也使容器有更大优势,使用容器可以在build或release 的阶段,为应用创建容器镜像,因为每个应用不需要与其余的应用堆栈组合,也不依赖于生产环境基础结构,这使得从研发到测试、生产能提供一致环境。类似地,容器比虚拟机轻量、更“透明”,这更便于监控和管理。
K8S 名词解释 #
使用腾讯云容器服务 TKE,会涉及到以下基本概念:
集群(Cluster):是指容器运行所需云资源的集合,包含了若干台云服务器、负载均衡器等云资源。
节点(Node):节点可以是一个虚拟机或者物理机器,取决于所在的集群配置,每个节点包含运行 Pods 所需的服务。
实例(Pod):由相关的一个或多个容器构成一个实例,这些容器共享相同的存储和网络空间。
工作负载(Workloads):Kubernetes 资源对象,用于管理 Pod 副本的创建、调度以及整个生命周期的自动控制。
Service:由多个相同配置的实例(Pod)和访问这些实例(Pod)的规则组成的微服务。
Ingress:Ingress 是用于将外部 HTTP(S)流量路由到服务(Service)的规则集合。
镜像仓库:用于存放 Docker 镜像,Docker 镜像用于部署容器服务。
常用指令
# 查看所有 pod 列表, -n 后跟 namespace, 查看指定的命名空间 kubectl get pods kubectl get pods -n game-demo NAME READY STATUS RESTARTS AGE game-dirsvr-1-6bd769896b-9vz58 2/2 Running 0 5d1h game-gamesvr-1-5b585b7fdc-vl7wr 2/2 Running 0 32m
一旦pod状态损坏后,CrashLoopBackOff,就进不了pod查看日志
kubectl get pods -n game-demo NAME READY STATUS RESTARTS AGE game-dirsvr-77c78ddc-r85bd 0/1 CrashLoopBackOff 165 14h game-gamesvr-6c7f448bc6-2ttnh 1/1 Running 0 14h
kubectl exec -n gamioo-demo --stdin --tty ooxxooxx -- /bin/bash # 通过bash获得 pod 中某个容器的TTY,相当于登录容器 kubectl exec -it <pod-name> -c <container-name> -- bash kubectl exec -n game-demo -it gamesvr-1-7f9f9f8bfb-hrwdn -c gamesvr-1 -- bash
# 执行 pod 的 date 命令 kubectl exec <pod-name> -- date kubectl exec <pod-name> -- bash kubectl exec <pod-name> -- ping 10.24.51.9 kubectl exec gamesvr-1-666dd5f8c8-d9lb6 -n gamioo-demo -c gamesvr-1 -- date Sun Jul 11 23:09:08 CST 2021
# 查看 Pod 详情: kubectl describe node 172.17.0.11 # 显示 Pod 的详细信息, 特别是查看 pod 无法创建的时候的日志 kubectl describe pod <pod-name> -n <namespace> kubectl describe pod gamesvr-1-666dd5f8c8-d9lb6 -n gamioo-demo
# 根据 yaml 创建资源, apply 可以重复执行,create 不行 kubectl create -f pod.yaml -n <namespace> kubectl apply -f pod.yaml -n <namespace> kubectl apply -f pod.yaml -n <namespace>
patch 更新 api 对象,使用策略性合并补丁更新一个 Deployment过补丁,您可以避免定义整个对象,只需要定义您希望更改的部分。通过策略性合并补丁,您只需要定义新增的元素就可以更新一个列表。列表中已有的元素仍然保留,新增的元素和已有的元素会被合并。上述例子中,最终结果的 containers 列表中既有原先的 nginx 容器,也有新增的 redis 容器。
如果能保证pod.yaml是最新的,那整个过程就不需要先apply,再patch,否则就变成了先部署老版本,再打patch新的版本上去的过程。
kubectl patch deployment <container-name> -n <namespace> -patch "json content" kubectl patch deployment dirsvr-1 -n gamioo-demo -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"build\":\"$REVISION-$DEPLOY_DATE\"}}}}}}" # 等价命令 kubectl patch deployment patch-demo --patch "$(cat patch-file.yaml)" kubectl patch deployment patch-demo --patch $'spec:\n template:\n spec:\n containers:\n - name: patch-demo-ctr-2\n image: redis' #如何传值 kubectl patch deployment patch-demo --patch "$(cat patch-file.json)" kubectl patch deployment patch-demo --patch '{"spec": {"template": {"spec": {"containers": [{"name": "patch-demo-ctr-2","image": "redis"}]}}}}' #删除 k8s 中的 StatefulSet kubectl delete statefulset gamesvr-1-1 -n gamioo-demo
#查看更新结果 kubectl get deployment gamesvr-1 -n gamioo-demo --output yaml spec: progressDeadlineSeconds: 600 replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: app: gamesvr-1 strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: creationTimestamp: null labels: app: gamesvr-1 build: 7ac2d40-1625837884
# 查看容器的日志 kubectl logs <pod-name> kubectl logs -f <pod-name> # 实时查看日志 kubectl logs <pod-name> -c <container_name> # 若 pod 只有一个容器,可以不加 -c #查看最近的10行日志 kubectl logs --tail 10 gamesvr-1-666dd5f8c8-d9lb6 -n gamioo-demo -c gamesvr-1 # 仅输出pod nginx中最近的20条日志 kubectl logs --tail=20 nginx # 输出pod nginx中最近一小时内产生的所有日志 kubectl logs --since=1h nginx
如果kubectl logs后没有任何输出,试试使用get pod,然后会发现这很有可能是一个新启动的Pod,因此可以尝试检查一些上一次挂掉的Pod的日志。
kubectl logs gamesvr-1-666dd5f8c8-d9lb6 -n gamioo-demo -c gamesvr-1 --previous
# 查看集群的所有节点信息 kubectl get node --show-labels NAME STATUS ROLES AGE VERSION LABELS 172.17.0.10 Ready <none> 101d v1.18.4-tke.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/fluentd-ds-ready=true,beta.kubernetes.io/instance-type=S5.LARGE8,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-8helzjev,failure-domain.beta.kubernetes.io/region=sh,failure-domain.beta.kubernetes.io/zone=200005,kubernetes.io/arch=amd64,kubernetes.io/hostname=172.17.0.10,kubernetes.io/os=linux,node.kubernetes.io/instance-type=S5.LARGE8,topology.kubernetes.io/region=sh,topology.kubernetes.io/zone=200005 172.17.0.11 Ready <none> 101d v1.18.4-tke.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/fluentd-ds-ready=true,beta.kubernetes.io/instance-type=S5.LARGE8,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-2qrbqrvz,failure-domain.beta.kubernetes.io/region=sh,failure-domain.beta.kubernetes.io/zone=200005,kubernetes.io/arch=amd64,kubernetes.io/hostname=172.17.0.11,kubernetes.io/os=linux,node.kubernetes.io/instance-type=S5.LARGE8,topology.kubernetes.io/region=sh,topology.kubernetes.io/zone=200005 172.17.0.5 Ready <none> 101d v1.18.4-tke.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/fluentd-ds-ready=true,beta.kubernetes.io/instance-type=S5.LARGE8,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-1sw1t7xn,failure-domain.beta.kubernetes.io/region=sh,failure-domain.beta.kubernetes.io/zone=200005,kubernetes.io/arch=amd64,kubernetes.io/hostname=172.17.0.5,kubernetes.io/os=linux,node.kubernetes.io/instance-type=S5.LARGE8,topology.kubernetes.io/region=sh,topology.kubernetes.io/zone=200005 172.17.0.6 Ready <none> 101d v1.18.4-tke.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/fluentd-ds-ready=true,beta.kubernetes.io/instance-type=S5.LARGE8,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-kf266cv9,failure-domain.beta.kubernetes.io/region=sh,failure-domain.beta.kubernetes.io/zone=200005,kubernetes.io/arch=amd64,kubernetes.io/hostname=172.17.0.6,kubernetes.io/os=linux,node.kubernetes.io/instance-type=S5.LARGE8,topology.kubernetes.io/region=sh,topology.kubernetes.io/zone=200005 172.17.0.8 Ready <none> 101d v1.18.4-tke.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/fluentd-ds-ready=true,beta.kubernetes.io/instance-type=S5.LARGE8,beta.kubernetes.io/os=linux,cloud.tencent.com/node-instance-id=ins-ifbkpk7j,failure-domain.beta.kubernetes.io/region=sh,failure-domain.beta.kubernetes.io/zone=200005,kubernetes.io/arch=amd64,kubernetes.io/hostname=172.17.0.8,kubernetes.io/os=linux,node.kubernetes.io/instance-type=S5.LARGE8,topology.kubernetes.io/region=sh,topology.kubernetes.io/zone=200005
整合两个指令:
kubectl exec -n gamioo-demo --stdin --tty $(kubectl get pods -n gamioo-demo | grep gamesvr | awk -F' ' '{print $1}') -- /bin/bash
如果起不来,排查如下:
kubectl logs --tail 10 gamioo-accountsvr-6dc4869f44-snb2v -n gamioo-demo -c gamioo-accountsvr //输出尾部的事件信息 kubectl describe pod gamioo-accountsvr --namespace=gamioo-demo kubectl delete deployment gamioo-accountsvr -n gamioo-demo kubectl get pods -n gamioo-demo kubectl get deployment gamioo-accountsvr -n gamioo-demo --output yaml #启动异常,没有日志时看这个 kubectl -n gamioo-demo get event
> kubectl describe pod logger Name: logger-68d7466799-r5pbf Namespace: platform-server Priority: 0 Node: 10.100.0.120/10.100.0.120 Start Time: Thu, 05 Jan 2023 17:08:22 +0800 Labels: app=logger build=f943d61 pod-template-hash=68d7466799 Annotations: tke.cloud.tencent.com/networks-status: [{ "name": "tke-route-eni", "interface": "eth1", "ips": [ "10.100.0.91" ], "mac": "42:f8:10:dc:c7:24", "default": true, "dns": {} }] Status: Running IP: 10.100.0.91 IPs: IP: 10.100.0.91 Controlled By: ReplicaSet/logger-68d7466799 Containers: logger: Container ID: docker://c621f177db202632ae44e800e389d8611f7d095c9c1c04c851c2320d60f7eddc Image: ccr.ccs.tencentyun.com/yorha-kf-demo/platform-logger:0.4.138.0 Image ID: docker-pullable://ccr.ccs.tencentyun.com/yorha-kf-demo/platform-logger@sha256:fd98232214f4437b40480e260a6c375008b1605f189e80814cddd00afa3e29d0 Port: 4001/TCP Host Port: 0/TCP Args: test 10.100.0.127:8848 State: Running Started: Thu, 05 Jan 2023 17:08:24 +0800 Ready: True Restart Count: 0 Limits: memory: 2048M tke.cloud.tencent.com/eni-ip: 1 Requests: memory: 1024M tke.cloud.tencent.com/eni-ip: 1 Environment: TZ: Asia/Shanghai PROC_NAME: logger Mounts: /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-v9btc (ro) Readiness Gates: Type Status cloud.tencent.com/load-balancer-backendgroup-ready True Conditions: Type Status cloud.tencent.com/load-balancer-backendgroup-ready True Initialized True Ready True ContainersReady True PodScheduled True Volumes: kube-api-access-v9btc: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true QoS Class: Burstable Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 8m47s default-scheduler Successfully assigned platform-server/logger-68d7466799-r5pbf to 10.100.0.120 Normal Pulling 8m46s kubelet Pulling image "ccr.ccs.tencentyun.com/yorha-kf-demo/platform-logger:0.4.138.0" Normal Pulled 8m46s kubelet Successfully pulled image "ccr.ccs.tencentyun.com/yorha-kf-demo/platform-logger:0.4.138.0" in 306.22646ms Normal Created 8m45s kubelet Created container logger Normal Started 8m45s kubelet Started container logger
目前热更流水线是打了新的镜像,里面包含要增量更新的class文件,再执行命令的。
可以支持直接把文件打入到指定pod的指定目录的命令
kubectl cp
如何将k8容器中文件下载到本地
kubectl cp -n namespace pod:path localpath
kubectl cp -n platform-server platform-system-58746bb8d9-4x6b5:/gamioo/log/system/white.log ./white.log
工作负载:
Deployment:启动时先启动新的pod,然后再关闭老的pod
StatefulSet:标识固定,先关闭老的pod,然后再开启新的pod
Replicaset:通过定义一个Deployment控制器会创建一个新的ReplicaSet控制器,然后再通过ReplicaSet创建pod。一般来说,删除Deployment控制器,同时会删除Deployment控制器下对应的ReplicaSet控制器和pod资源。
是pod控制器类型的一种实现,用于确保由其管控的pod对象副本数在任一时刻都能精确满足期望的数量。ReplicaSet控制器资源启动后会查找集群中匹配其标签选择器的pod资源对象,当前活动对象的数量与其期望的数量不吻合时,多则删除,少则通过pod模板创建以补足,等pod资源副本数量符合期望值后即进入下一轮和解循环。
默认情况下,将保留 10 个旧的 ReplicaSet,但其理想值取决于新 Deployment 的频率和稳定性,我们可以通过
修改spec.revisionHistoryLimit 的值去改变,
apiVersion: apps/v1 kind: Deployment # ... spec: # ... revisionHistoryLimit: 0 # Default to 10 if not specified # ...
引用自 K8s 文档:«.spec.revisionHistoryLimit 是一个可选字段,它指定要保留以允许回滚的旧 ReplicaSets 的数量。这些旧的 ReplicaSet 会消耗 etcd 中的资源并挤占 kubectl get rs 的输出。每个 Deployment 修订版的配置都存储在其 ReplicaSets 中;因此,一旦旧的 ReplicaSet 被删除,您就无法回滚到 Deployment 的那个修订版。
一个pod相当于一个操作系统,容器(Container)相当于一个进程,一个pod可以有好多个进程
Q&A
1.进程启动比正常慢很多,可能原因是对CPU做了上下限限制,取消限制就行。
2. K8Spod资源调度经常调度到内存占用大的宿主机,而不是内存占用小的。
原因是因为容器调度策略默认以CPU为主,
kubernetes之镜像拉取策略ImagePullSecrets
2.如何自定义容器调度策略
如何使用
这样就可以按照内存权重优先来调度啦。