K8S常用操作

kubectl命令行的语法如下:

kubectl [command] [TYPE] [NAME] [flags]
  • command: 子命令,用于操作k8s集群资源对象,例如 create,delete,describe,get,apply,logs,edit,config等

删除pod service namespace deployment

kubectl delete -f xxx.yaml
kubectl delete pod POD_NAME -n SPACE_NAME
kubectl delete pod POD_NAME --grace-period=0 -n SPACE_NAME	# 1.4以前的版本 强制删除
kubectl delete pod POD_NAME --grace-period=0 --force -n SPACE_NAME	# 1.5以后的版本 强制删除

有时会遇到一些Pod已经不需要了,但找不到当时部署的 .yaml文件或创建方法,删除pod会自动创建时,通过以下思路来进行删除

kubectl get deployment -n SPACE_NAME		# 查看对应命名空间下有哪些deployment 
kubectl delete deployment DEPLOYMENT_NAME	# 删除跟pod对应的deployment,pod就会自动删除

给node设置label

kubectl label nodes NODES_NAME_1 slave=test-01
kubectl label nodes NODES_NAME_2 zone=wuhan

kubectl get nodes --show-labels

删除node label,在label的键后面加一个减号即可

kubectl label nodes test-04 slave-
kubectl label nodes test-04 zone-

查看pod 日志, kubectl logs NAMESPACES PODNAME

kubectl logs -n kube-system calico-node-pqc7x

手动扩容

kubectl scale deploy test-k8s -n kube-system --replicas 3	# 调整test-k8s服务的pod数量为3,如果原来pod数量大于3,则关闭超出部分;如果原来pod数量小于3,则自动增加至3个

kubectl edit

	kubectl edit deployment POD_NAME -n NAMESAPCE	# 命令行改pod配置
	kubectl edit service SVC_NAME -n NAMESAPCE	# 命令行改serivce配置
				 secert
	             ingress

官方教程操作笔记

# 直接创建一个deployment应用
kubectl create deployment nginx-web --image=nginx

# scale 更改pod副本数量
kubectl scale deployment nginx-web --replicas=3


# 将k8s的API代理到本地的8001端口,以便通过API访问集群信息
kubecrl proxy

# 查看指定pod相关信息,类似用`kubectl describe`命令
curl http://127.0.0.1:8001/api/v1/namespaces/kube-system/pods/$POD_NAME	

# 查看指定命令空间所有的pod、服务等,具体可查内容参考`kubectl describe --help`
kubectl describe po|svc|all $NAMESPACES 

# 暴露服务端口,方便集群外部访问
kubectl expose deployment/nginx-web --type="NodePort" --port 80

kubectl get svc 

kubectl describe svc nginx-web

# 查询指定服务的NodePort具体端口号,并赋值给变量NODE_PORT
NODE_PORT=$(kubectl get services/nginx-web -o go-template='{{(index .spec.ports 0).nodePort}}')
echo NODE_PORT=$NODE_PORT

# 基于文件创建ConfigMap
kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt

# 基于指定变量创建ConfigMap
kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2

# 从指定文件中读取key=value创建ConfigMap
kubectl create configmap my-config --from-file=path/to/bar

# 基于指定环境变量文件创建对应的ConfigMap
kubectl create configmap my-config --from-env-file=path/to/foo.env --from-env-file=path/to/bar.env

# 进入pod查看资源消耗情况 
kubectl exec -n kube-system api-6b9f74f658-84swn -- top -bn2

安全清空节点

  • '--ignore-daemonsets'忽略deamonset控制器的pod,不然会删除了pod也会自动重建导致死循环。

  • '--delete-local-data'参数,即使pod使用了emptyDir也删除

  • '–force' 不加force参数只会删除该NODE上由ReplicationController, ReplicaSet, DaemonSet,StatefulSet or Job创建的Pod,加了后还会删除’裸奔的pod’(没有绑定到任何replication controller)

# 配置为不可调度,防止有新的pod分配到这个节点 
kubectl cordon NODE_NAME

# 清空节点
kubectl drain NODE_NAME --ignore-daemonsets

# 维护结束后如果还要用这个节点,用以下命令恢复节点调度
kubectl uncordon NODE_NAME

批量删除容器日志

#! /bin/bash
for CORE_NAME in "$(kubectl get po -n kube-system | grep -E '\-core|api' | awk -F ' ' '{print $1}')"
do
kubectl exec -itn kube-system "${CORE_NAME}" -- bash -c "cd /usr/local/tomcat/logs/ && echo > catalina.out && find ./*log -mtime +3 -exec rm -rf {} \; && find ./*txt -mtime +3 -exec rm -rf {} \;" || \
kubectl exec -itn kube-system "${CORE_NAME}" -- bash -c "cd /app/tomcat/logs/ && echo > catalina-$(date +%F).out && find ./*out -mtime +3 -exec rm -rf {} \; && find ./*txt -mtime +3 -exec rm -rf {} \;" 
done

不进Pod执行命令

kubectl exec -itn NAMESPACES PODNAME -- bash -c "command" # 不推荐,shell环境不一定兼容

# 推荐
kubectl exec -itn NAMESPACES PODNAME -- ps aux
kubectl exec shell-demo -- cat /proc/1/mounts

不进Pod打印容器中的环境变量

kubectl exec -n NAMESPACES PODNAME env

pod 开启特权模式,在containers下面加上securityContext: privileged: true

      containers:
      - name: test
        image: nginx
        imagePullPolicy: IfNotPresent
        securityContext:
          privileged: true

pod 使用nfs挂载volumes时,运行pod的NODE上需要安装nfs,否则会无法挂载成功

yum install -y nfs-utils	# CentOS
apt install -y nfs-common	# Debian or Ubuntu

services 会话保持,在service 的yaml文件中的spec下增加如下配置

sessionAffinity: ClientIP
sessionAffinityConfig:
	clientIP:
	  timeoutSeconds: 10800		# session 保持时间,单位 秒

查看所有pod,以启动时间排序

kubectl get po -n NAMESPACES --sort-by=.status.startTime -o wide

查看api信息及CA证书

kubectl cluster-info | grep 'Kubernetes master' | awk '/http/ {print $NF}'
kubectl get secrets
kubectl get secrets default-token-jnc9t -o jsonpath="{['data']['ca\.crt']}" | base64 --decode

nodeport 80 # 节点端口,可以通过节点IP访问服务 port 80 # 服务(service)端口,clusterIP:80 集群内可以通过clusterIP:port 访问服务 targetport 80 # 容器(pod)端口,nodePort 和 port 最终将服务转发到targetport,由Pod提供服务


Deployment滚动升级和回滚

# 使用apply来部署,会只重新部署跟之前yaml文件中不同的配置。
# 例如在yaml文件中只修改了Deployment部分的配置,Services 和 Ingress都没修改,那在使用apply来部署的时候,就只会重新部署Deployment.
kubectl apply -f deployment.yaml --record=true	# --record 记录历史,这样在使用rollout history时才能看到历史版本。新版本中--record参数将会删除

# 回滚操作
kubectl rollout history deployment/POD_NAME -n NAMESPACES	# 查看历史版本,编号越大越新,最大一版为当前版
kubectl rollout undo deployment/POD_NAME -n NAMESPACES # 回滚到上一版本
kubectl rollout undo deployment/POD_NAME --to-revision=2 -n NAMESPACES  # 回滚到第2版本

一个pod中有多个容器时,如何操作指定容器

# 我通过yaml文件定义了一个pod包含两个容器,'containers'下的'name'配置分别为'test-nginx'和'test-nginx-filebeat'
kubectl get po -n kube-system | grep nginx
test-nginx-5bc8898fc9-fbdg4         2/2       Running   0          8m

# 查看指定容器的日志,要在pod后面接上对应容器的'name',其它操作也一样
kubectl logs -f -n kube-system test-nginx-5bc8898fc9-fbdg4 test-nginx-filebeat

# 要进入指定容器时,用-c参数
kubectl -itn kube-system test-nginx-5bc8898fc9-fbdg4 -c test-nginx-filebeat -- bash


Init容器

Init 容器是一种特殊容器,在 Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本。

使用 Init 容器的示例 下面的例子定义了一个具有 2 个 Init 容器的简单 Pod。 第一个等待 myservice 启动, 第二个等待 mydb 启动。 一旦这两个 Init 容器都启动完成,Pod 将启动 spec 节中的应用容器。

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app.kubernetes.io/name: MyApp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]

临时容器

临时容器与其他容器的不同之处在于,它们缺少对资源或执行的保证,并且永远不会自动重启, 因此不适用于构建应用程序。 临时容器使用与常规容器相同的 ContainerSpec 节来描述,但许多字段是不兼容和不允许的。

  • 临时容器没有端口配置,因此像 portslivenessProbereadinessProbe 这样的字段是不允许的。

  • Pod 资源分配是不可变的,因此 resources 配置是不允许的。

  • 有关允许字段的完整列表,请参见 EphemeralContainer 参考文档。

临时容器是使用 API 中的一种特殊的 ephemeralcontainers 处理器进行创建的, 而不是直接添加到 pod.spec 段,因此无法使用 kubectl edit 来添加一个临时容器。

与常规容器一样,将临时容器添加到 Pod 后,将不能更改或删除临时容器。

当由于容器崩溃或容器镜像不包含调试工具而导致 kubectl exec 无用时, 临时容器对于交互式故障排查很有用。

使用临时容器来调试的例子

你可以使用 kubectl debug 命令来给正在运行中的 Pod 增加一个临时容器。 首先,像示例一样创建一个 pod:

kubectl run ephemeral-demo --image=registry.k8s.io/pause:3.1 --restart=Never

本节示例中使用 pause 容器镜像,因为它不包含调试程序,但是这个方法适用于所有容器镜像。

如果你尝试使用 kubectl exec 来创建一个 shell,你将会看到一个错误,因为这个容器镜像中没有 shell。

kubectl exec -it ephemeral-demo -- sh
OCI runtime exec failed: exec failed: container_linux.go:346: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown

你可以改为使用 kubectl debug 添加调试容器。 如果你指定 -i 或者 --interactive 参数,kubectl 将自动挂接到临时容器的控制台。

kubectl debug -it ephemeral-demo --image=busybox:1.28 --target=ephemeral-demo
Defaulting debug container name to debugger-8xzrl.
If you don't see a command prompt, try pressing enter.
/ #

此命令添加一个新的 busybox 容器并将其挂接到该容器。--target 参数指定另一个容器的进程命名空间。 这个指定进程命名空间的操作是必需的,因为 kubectl run 不能在它创建的 Pod 中启用共享进程命名空间。

说明: 容器运行时必须支持 --target 参数。 如果不支持,则临时容器可能不会启动,或者可能使用隔离的进程命名空间启动, 以便 ps 不显示其他容器内的进程。

最后更新于