Skip to content

2024

k8s troubleshooting error scale

不明原因scale扩容失败,容器起不来

Problem
[root@k8s-master ~]# kubectl get rs,po
NAME                                      DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deploy-548d7bc8bc   1         1         0       16m
replicaset.apps/nginx-deploy-5f44797d7f   1         1         0       13m
replicaset.apps/nginx-deploy-674dcdf579   2         2         2       17h
replicaset.apps/nginx-deploy-f7f5656c7    0         0         0       17h

NAME                                READY   STATUS              RESTARTS   AGE
pod/my-nginx                        1/1     Running             0          19h
pod/nginx-deploy-548d7bc8bc-pfhmn   0/1     ContainerCreating   0          16m
pod/nginx-deploy-5f44797d7f-jtmsd   0/1     ContainerCreating   0          13m
pod/nginx-deploy-674dcdf579-5gvbw   1/1     Running             0          17h
pod/nginx-deploy-674dcdf579-l79w8   1/1     Running             0          17h
pod/nginx-deploy-674dcdf579-t979q   0/1     Terminating         0          26m
[root@k8s-master ~]# kubectl edit deploy nginx-deploy
Pod_describe-nginx-deploy-548d7bc8bc-pfhmn
[root@k8s-master ~]# kubectl describe pod/nginx-deploy-548d7bc8bc-pfhmn
Name:           nginx-deploy-548d7bc8bc-pfhmn
Namespace:      default
Priority:       0
Node:           k8s-node1/10.0.0.101
Start Time:     Thu, 25 Apr 2024 22:10:19 -0400
Labels:         app=nginx-deploy
                pod-template-hash=548d7bc8bc
Annotations:    <none>
Status:         Pending
IP:             
IPs:            <none>
Controlled By:  ReplicaSet/nginx-deploy-548d7bc8bc
Containers:
nginx:
    Container ID:   
    Image:          nginx:1.25.5
    Image ID:       
    Port:           <none>
    Host Port:      <none>
    State:          Waiting
    Reason:       ContainerCreating
    Ready:          False
    Restart Count:  0
    Requests:
    cpu:        100m
    memory:     128Mi
    Environment:  <none>
    Mounts:
    /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-v5qt4 (ro)
Conditions:
Type              Status
Initialized       True 
Ready             False 
ContainersReady   False 
PodScheduled      True 
Volumes:
kube-api-access-v5qt4:
    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               24m                   default-scheduler  Successfully assigned default/nginx-deploy-548d7bc8bc-pfhmn to k8s-node1
Warning  FailedCreatePodSandBox  24m                   kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = [failed to set up sandbox container "d0c52072346d605a7594b91391ccd8ceb7803a629412e165a0e49f8b1fb498ba" network for pod "nginx-deploy-548d7bc8bc-pfhmn": networkPlugin cni failed to set up pod "nginx-deploy-548d7bc8bc-pfhmn_default" network: error getting ClusterInformation: connection is unauthorized: Unauthorized, failed to clean up sandbox container "d0c52072346d605a7594b91391ccd8ceb7803a629412e165a0e49f8b1fb498ba" network for pod "nginx-deploy-548d7bc8bc-pfhmn": networkPlugin cni failed to teardown pod "nginx-deploy-548d7bc8bc-pfhmn_default" network: error getting ClusterInformation: connection is unauthorized: Unauthorized]
Normal   SandboxChanged          3m58s (x97 over 24m)  kubelet            Pod sandbox changed, it will be killed and re-created.
Deployment_yaml_file
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
    deployment.kubernetes.io/revision: "7"
creationTimestamp: "2024-04-25T07:44:53Z"
generation: 9
labels:
    app: nginx-deploy
name: nginx-deploy
namespace: default
resourceVersion: "77441"
uid: 02e581e3-6bbd-4af9-9d3a-9eda5b1c790b
spec:
progressDeadlineSeconds: 600
replicas: 3
revisionHistoryLimit: 10
selector:
    matchLabels:
    app: nginx-deploy
strategy:
    rollingUpdate:
    maxSurge: 25%
    maxUnavailable: 25%
    type: RollingUpdate
template:
    metadata:
    creationTimestamp: null
    labels:
        app: nginx-deploy
        spec:
    containers:
    - image: nginx:1.25.5
        imagePullPolicy: IfNotPresent
        name: nginx
        resources:
        requests:
            cpu: 200m
            memory: 256Mi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
    dnsPolicy: ClusterFirst
    restartPolicy: Always
    schedulerName: default-scheduler
    securityContext: {}
    terminationGracePeriodSeconds: 30
status:
availableReplicas: 2
conditions:
- lastTransitionTime: "2024-04-26T02:00:13Z"
    lastUpdateTime: "2024-04-26T02:00:13Z"
    message: Deployment does not have minimum availability.
    reason: MinimumReplicasUnavailable
    status: "False"
    type: Available
- lastTransitionTime: "2024-04-26T02:22:40Z"
    lastUpdateTime: "2024-04-26T02:22:40Z"
    message: ReplicaSet "nginx-deploy-5f44797d7f" has timed out progressing.
    reason: ProgressDeadlineExceeded
    status: "False"
    type: Progressing
observedGeneration: 9
readyReplicas: 2
    replicas: 4
unavailableReplicas: 2
updatedReplicas: 1

参考这个issue

最简单是通过重启Master解决。

k8s troubleshooting Ingress

创建Ingress报错

[root@k8s-master ingress]# kubectl create -f wolfcode-ingress.yaml 
Error from server (InternalError): error when creating "wolfcode-ingress.yaml": Internal error occurred: failed calling webhook "validate.nginx.ingress.kubernetes.io": failed to call webhook: Post "https://ingress-nginx-controller-admission.ingress-nginx.svc:443/networking/v1/ingresses?timeout=10s": service "ingress-nginx-controller-admission" not found

解决方案

执行

[root@k8s-master ingress]# kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission
validatingwebhookconfiguration.admissionregistration.k8s.io "ingress-nginx-admission" deleted

再次创建Ingress

[root@k8s-master ingress]# kubectl create -f wolfcode-ingress.yaml 
ingress.networking.k8s.io/wolfcode-nginx-ingress created

k8s Resources Schedule

相关概念

  • Deployment: 部署包含RS、创建RS和pod,对应用程序进行滚动更新/滚动、动态扩缩容等 (RS:111)
  • RS(ReplicaSet): 副本集,管理Pod副本扩容/缩容
  • Selector: 查询器,相当于查询条件:type=xxx,name!=xxxx
  • StatefulSet : 专门对有状态服务进行部署的一个控制器

一. Label&Selector Usage

Label

临时创建标签
[root@k8s-master pods]# kubectl label po <pod name> app=hello
pod/my-nginx labeled
查看pod的标签
[root@k8s-master pods]# kubectl get po --show-labels
NAME       READY   STATUS    RESTARTS   AGE     LABELS
my-nginx   1/1     Running   0          3m10s   app=hello,type=app,version=1.0.x
修改已存在的标签
kubectl label po <pod name> app=hello222

Selector

配置文件

在各对象的配置 spec.selector 或其他可以写 selector 的属性中编写

kubectl

匹配单个值,查找 app=hello 的 pod

kubectl get po -A -l app=hello
匹配多个值
kubectl get po -A -l 'k8s-app in (metrics-server, kubernetes-dashboard)'
或查找 version!=1 and app=nginx 的 pod 信息
kubectl get po -l version!=1,app=nginx
不等值 + 语句
kubectl get po -A -l version!=1,'app in (busybox, nginx)'

二. Deployment Usage

Ⅰ. 功能

创建资源

命令行创建一个 deployment

kubectl create deploy nginx-deploy --image=nginx:1.26.0 
#也可以后面加 -o yaml 以yaml格式把内容输出,并创建资源
#也可以后面加 -o yaml > xxx.yaml 以yaml格式把内容输出到xxx.yaml文件,并创建资源
或执行
kubectl create -f xxx.yaml --record
#--record 会在 annotation 中记录当前命令创建或升级了资源,后续可以查看做过哪些变动操作。
查看部署信息
[root@k8s-master deployments]# kubectl get deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   1/1     1            1           2m4s
[root@k8s-master deployments]# kubectl get replicaset
NAME                      DESIRED   CURRENT   READY   AGE
nginx-deploy-744cbf6b5c   1         1         1       2m8s
[root@k8s-master deployments]# kubectl get pod
NAME                            READY   STATUS    RESTARTS   AGE
my-nginx                        1/1     Running   0          71m
nginx-deploy-744cbf6b5c-kl48m   1/1     Running   0          2m12s
[root@k8s-master deployments]# 

Tip

通过查询注意到,通过deployment创建的资源,pod name,rs name ,deployment name 三者有对应的关系。

滚动更新

只有修改了 k8s集群的 deployment 配置文件中的 template 中的属性后,才会触发更新操作

[root@k8s-master deployments]# kubectl get deploy
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   1/1     1            1           29m
[root@k8s-master deployments]# kubectl edit deploy nginx-deploy

修改 nginx 版本号

kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1

#或者通过 kubectl edit deployment/nginx-deployment 进行修改

查看滚动更新的过程

kubectl rollout status deploy <deployment_name>

查看部署描述,最后展示发生的事件列表也可以看到滚动更新过程

kubectl describe deploy <deployment_name>

  • 通过 kubectl get deployments 获取部署信息,UP-TO-DATE 表示已经有多少副本达到了配置中要求的数目

  • 通过 kubectl get rs 可以看到增加了一个新的 rs

  • 通过 kubectl get pods 可以看到所有 pod 关联的 rs 变成了新的

多个滚动更新并行

  • 假设当前有 5 个 nginx:1.7.9 版本,你想将版本更新为 1.9.1,当更新成功第三个以后,你马上又将期望更新的版本改为 1.9.2,那么此时会立马删除之前的三个,并且立马开启更新 1.9.2 的任务
回滚

有时候你可能想回退一个Deployment,例如,当Deployment不稳定时,比如一直crash looping。

默认情况下,kubernetes会在系统中保存前两次的Deployment的rollout历史记录,以便你可以随时会退(你可以修改revision history limit来更改保存的revision数)。

案例: 更新 deployment 时参数不小心写错,如 nginx:1.9.1 写成了 nginx:1.91

kubectl set image deployment/nginx-deploy nginx=nginx:1.91

监控滚动升级状态,由于镜像名称错误,下载镜像失败,因此更新过程会卡住

kubectl rollout status deployments nginx-deploy
结束监听后,获取 rs 信息,我们可以看到新增的 rs 副本数是 2 个
kubectl get rs
通过 kubectl get pods 获取 pods 信息,我们可以看到关联到新的 rs 的 pod,状态处于 ImagePullBackOff 状态

为了修复这个问题,我们需要找到需要回退的 revision 进行回退,通过:

 kubectl rollout history deployment/nginx-deploy 
可以获取 revison 的列表

通过:

kubectl rollout history deployment/nginx-deploy --revision=2 
可以查看详细信息

确认要回退的版本后,可以通过:

kubectl rollout undo deployment/nginx-deploy 
可以回退到上一个版本,也可以回退到指定的 revision:
kubectl rollout undo deployment/nginx-deploy --to-revision=2
再次通过:
kubectl get deployment 和 kubectl describe deployment
可以看到,我们的版本已经回退到对应的 revison 上了

通过设置 .spec.revisonHistoryLimit 来指定 deployment 保留多少 revison,如果设置为 0,则不允许 deployment 回退了。

扩容缩容

通过 kube scale 命令可以进行自动扩容/缩容,以及通过 kube edit 编辑 replcas 也可以实现扩容/缩容

kubectl scale --replicas=3 deploy nginx-deploy

扩容与缩容只是直接创建副本数,没有更新 pod template 因此不会创建新的 rs

暂停与恢复

由于每次对 pod template 中的信息发生修改后,都会触发更新 deployment 操作,那么此时如果频繁修改信息,就会产生多次更新,而实际上只需要执行最后一次更新即可,当出现此类情况时我们就可以暂停 deployment 的 rollout

通过 kubectl rollout pause deployment <name> 就可以实现暂停,直到你下次恢复后才会继续进行滚动更新

尝试对容器进行修改,然后查看是否发生更新操作了 kubectl set image deploy nginx=nginx:1.17.9 kubectl get po

通过以上操作可以看到实际并没有发生修改,此时我们再次进行修改一些属性,如限制 nginx 容器的最大cpu为 0.2 核,最大内存为 128M,最小内存为 64M,最小 cpu 为 0.1 核 kubectl set resources deploy -c --limits=cpu=200m,memory=128Mi --requests=cpu100m,memory=64Mi

通过格式化输出 kubectl get deploy -oyaml,可以看到配置确实发生了修改,再通过 kubectl get po 可以看到 pod 没有被更新

那么此时我们再恢复 rollout,通过命令 kubectl rollout deploy

恢复后,我们再次查看 rs 和 po 信息,我们可以看到就开始进行滚动更新操作了 kubectl get rs kubectl get po

配置文件

apiVersion: apps/v1 # deployment api 版本
kind: Deployment # 资源类型为 deployment
metadata: # 元信息
  labels: # 标签
    app: nginx-deploy # 具体的 key: value 配置形式
  name: nginx-deploy # deployment 的名字
  namespace: default # 所在的命名空间
spec:
  replicas: 1 # 期望副本数
  revisionHistoryLimit: 10 # 进行滚动更新后,保留的历史版本数
  selector: # 选择器,用于找到匹配的 RS
    matchLabels: # 按照标签匹配
      app: nginx-deploy # 匹配的标签key/value
  strategy: # 更新策略
    rollingUpdate: # 滚动更新配置
      maxSurge: 25% # 进行滚动更新时,更新的个数最多可以超过期望副本数的个数/比例
      maxUnavailable: 25% # 进行滚动更新时,最大不可用比例更新比例,表示在所有副本数中,最多可以有多少个不更新成功
    type: RollingUpdate # 更新类型,采用滚动更新
  template: # pod 模板
    metadata: # pod 的元信息
      labels: # pod 的标签
        app: nginx-deploy
    spec: # pod 期望信息
      containers: # pod 的容器
      - image: nginx:1.7.9 # 镜像
        imagePullPolicy: IfNotPresent # 拉取策略
        name: nginx # 容器名称
      restartPolicy: Always # 重启策略
      terminationGracePeriodSeconds: 30 # 删除操作最多宽限多长时间

三. StatefulSet

alt text

功能

创建

kubectl create -f web.yaml

# 查看 service 和 statefulset => sts
kubectl get service nginx
kubectl get statefulset web

# 查看 PVC 信息
kubectl get pvc

# 查看创建的 pod,这些 pod 是有序的
kubectl get pods -l app=nginx

# 查看这些 pod 的 dns
# 运行一个 pod,基础镜像为 busybox 工具包,利用里面的 nslookup 可以看到 dns 信息
kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh
nslookup web-0.nginx
更新yaml配置文件后可以用replace来更新资源
kubectl replace sts web -f web.yaml

访问容器

像docker一样用命令简单创建一个容器:

kubectl run -it --image busybox dns-test --restart=Never --rm /bin/sh

访问其他容器: alt text

[root@k8s-master statefulset]# kubectl run -it --image busybox dns-test --restart=Never --rm /bin/sh
/ # ping web-1.nginx  #验证容器间访问
PING web-1.nginx (192.168.36.100): 56 data bytes
64 bytes from 192.168.36.100: seq=0 ttl=62 time=0.327 ms
64 bytes from 192.168.36.100: seq=1 ttl=62 time=0.289 ms
...
/ # ping web-0.nginx   #验证容器间访问
PING web-0.nginx (192.168.169.161): 56 data bytes
64 bytes from 192.168.169.161: seq=0 ttl=63 time=0.051 ms
64 bytes from 192.168.169.161: seq=1 ttl=63 time=0.051 ms

注释:

  • dns-test : 容器名称
  • busybox : linux的常用工具镜像
  • --restart=Never: 当探测到容器失败是否重启 POD
  • --rm : 运行完后删除容器
  • /bin/sh: 进入容器的目录(执行bin目录下的sh)
扩容缩容
# 扩容

$ kubectl scale statefulset web --replicas=5

# 缩容2种方法
$ kubectl scale sts web --replicas=2
$ kubectl patch statefulset web -p '{"spec":{"replicas":3}}'
镜像更新
# 镜像更新(目前还不支持直接更新 image,需要 patch 来间接实现)
kubectl patch sts web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"nginx:1.9.1"}]'
RollingUpdate

StatefulSet 也可以采用滚动更新策略,同样是修改 pod template 属性后会触发更新,但是由于 pod 是有序的,在 StatefulSet 中更新时是基于 pod 的顺序倒序更新的

查看rolling 状态

[root@k8s-master statefulset]# kubectl rollout status sts web
partitioned roll out complete: 2 new pods have been updated...
查看statefulset更新记录
kubectl rollout history sts web

灰度发布(金丝雀)

利用滚动更新中的 partition 属性,可以实现简易的灰度发布的效果

例如我们有 5 个 pod,如果当前 partition 设置为 3,那么此时滚动更新时,只会更新那些 序号 >= 3 的 pod

利用该机制,我们可以通过控制 partition 的值,来决定只更新其中一部分 pod,确认没有问题后再主键增大更新的 pod 数量,最终实现全部 pod 更新

Statefulset的滚动更新是先删除再创建

下面是先删除再创建的原因:

数据的持久性:有状态应用程序通常使用持久卷(Persistent Volume)来存储数据。在进行更新时,先删除旧的 Pod,可以确保旧 Pod 使用的持久卷不会被意外删除,从而保留数据的持久性。

网络标识的稳定性:StatefulSet 的每个 Pod 都有唯一的标识符和稳定的网络标识。这些标识符通常基于 Pod 的名称和索引。通过先删除旧的 Pod,再创建新的 Pod,可以保证新 Pod 的名称和索引与旧 Pod 保持一致,从而保持网络标识的稳定性。

依赖关系的管理:在有状态应用程序中,可能存在依赖其他 Pod 的情况,例如数据库集群中的主从关系。通过先删除再创建的方式,可以确保新创建的 Pod 在依赖关系方面与旧 Pod 保持一致,避免因更新过程中引入不一致性。

OnDelete

只有在 pod 被删除时会进行更新操作

删除
# 删除 StatefulSet 和 Headless Service
# 级联删除:删除 statefulset 时会同时删除 pods
kubectl delete statefulset web
# 非级联删除:删除 statefulset 时不会删除 pods,删除 sts 后,pods 就没人管了,此时再删除 pod 不会重建的
kubectl deelte sts web --cascade=false
# 删除 service
kubectl delete service nginx
删除pvc
# StatefulSet删除后PVC还会保留着,数据不再使用的话也需要删除
$ kubectl delete pvc www-web-0 www-web-1

配置文件

---
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"  #使用哪个service 来管理dns
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80  #容器内部要暴露的端口
          name: web  #该端口的名字
        volumeMounts:
        - name: www  #指定加载哪个数据卷
          mountPath: /usr/share/nginx/html  #加载到容器的哪个目录
  volumeClaimTemplates: # 数据卷模板
  - metadata:  #数据卷描述
      name: www  #数据卷名称
      annotations:  #数据卷注释
        volume.alpha.kubernetes.io/storage-class: anything
    spec:  #数据卷的规约
      accessModes: [ "ReadWriteOnce" ]  #访问模式
      resources:
        requests:
          storage: 1Gi  #存储大小

k8s PodProbe

探针三个类型

The kubelet uses liveness probes to know when to restart a container. For example, liveness probes could catch a deadlock, where an application is running, but unable to make progress. Restarting a container in such a state can help to make the application more available despite bugs.

1. StartupProbe

k8s 1.16 版本新增的探针,用于判断应用程序是否已经启动了。

当配置了 startupProbe 后,会先禁用其他探针,直到 startupProbe 成功后,其他探针才会继续。

作用:由于有时候不能准确预估应用一定是多长时间启动成功,因此配置另外两种方式不方便配置初始化时长来检测,而配置了 statupProbe 后,只有在应用启动成功了,才会执行另外两种探针,可以更加方便的结合使用另外两种探针使用。

startupProbe:
  httpGet:
    path: /api/startup
    port: 80

2. LivenessProbe

用于探测容器中的应用是否运行,如果探测失败,kubelet 会根据配置的重启策略进行重启,若没有配置,默认就认为容器启动成功,不会执行重启策略。

livenessProbe:
  failureThreshold: 5
  httpGet:
    path: /health
    port: 8080
    scheme: HTTP
  initialDelaySeconds: 60
  periodSeconds: 10
  successThreshold: 1
  timeoutSeconds: 5

3. ReadinessProbe

用于探测容器内的程序是否健康,它的返回值如果返回 success,那么就认为该容器已经完全启动,并且该容器是可以接收外部流量的。

readinessProbe:
  failureThreshold: 3 # 错误次数
  httpGet:
    path: /ready
    port: 8181
    scheme: HTTP
  periodSeconds: 10 # 间隔时间
  successThreshold: 1
  timeoutSeconds: 1

探测方法

1. ExecAction

在容器内部执行一个命令,如果返回值为 0,则任务容器时健康的。

livenessProbe:
  exec:
    command:
      - cat
      - /health

2. TCPSocketAction

通过 tcp 连接监测容器内端口是否开放,如果开放则证明该容器健康

livenessProbe:
  tcpSocket:
    port: 80

3. HTTPGetAction

生产环境用的较多的方式,发送 HTTP 请求到容器内的应用程序,如果接口返回的状态码在 200~400 之间,则认为容器健康。

livenessProbe:
  failureThreshold: 5
  httpGet:
    path: /health
    port: 8080
    scheme: HTTP
    httpHeaders:
      - name: xxx
        value: xxx

参数配置

  • initialDelaySeconds: 60 # 初始化时间
  • timeoutSeconds: 2 # 超时时间
  • periodSeconds: 5 # 监测间隔时间
  • successThreshold: 1 # 检查 1 次成功就表示成功
  • failureThreshold: 2 # 监测失败 2 次就表示失败

k8s Pod Lifecycle

This page describes the lifecycle of a Pod. Pods follow a defined lifecycle, starting in the Pending phase, moving through Running if at least one of its primary containers starts OK, and then through either the Succeeded or Failed phases depending on whether any container in the Pod terminated in failure.

alt text

K8s cluster -- kubeadm

prerequisition:

  • 3台服务器或虚拟机
  • 最低配置:2CPU、2GB Memory、20GB disk
  • 最好能联网,不能联网需要有提供队友镜像的私有仓库 .

软件环境:

  • 操作系统:centos7
  • Docker: 20+
  • k8s:1.23.6

安装步骤:

1. 初始操作(所有节点)
关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
关闭selinux
sed -i 's/enforcing/disabled/' /etc/selinux/config  # 永久
setenforce 0  # 临时
关闭swap

swapoff -a  # 临时
sed -ri 's/.*swap.*/#&/' /etc/fstab    # 永久
关闭完swap后,一定要重启一下虚拟机!!!

根据规划设置主机名
hostnamectl set-hostname <hostname>
在master添加hosts
cat >> /etc/hosts << EOF
192.168.113.120 k8s-master
192.168.113.121 k8s-node1
192.168.113.122 k8s-node2
EOF
将桥接的IPv4流量传递到iptables的链
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

sysctl --system  # 生效
时间同步
yum install ntpdate -y
ntpdate time.windows.com
2. 安装基础软件(所有节点)
基于文档中的安装 Docker 文件进行安装
Uninstall old versions

sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine

Set up the repository

sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
本实验按装Docker 20+
[root@node1 yum.repos.d]# yum list docker-ce --showduplicates | sort -r
* updates: mirrors.bupt.edu.cn
Loading mirror speeds from cached hostfile
Loaded plugins: fastestmirror
* extras: mirrors.nju.edu.cn
docker-ce.x86_64            3:26.0.2-1.el7                      docker-ce-stable
docker-ce.x86_64            3:26.0.1-1.el7                      docker-ce-stable
<...>
[root@node1 yum.repos.d]#sudo yum install docker-ce-3:23.0.1-1.el7 docker-ce-cli-3:23.0.1-1.el7 containerd.io docker-buildx-plugin docker-compose-plugin

启动docker 出现 ‘ Failed to start docker.service: Unit not found. ’ 错误 ,因为缺少 rhel-push-plugin.socket 单元,该单元是rhel-push-plugin软件包的一部分。所以我们执行以下指令就可以成功解决curl -sSL https://get.docker.com/ | sh 提示。安装最新版本的命令是: sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Install Docker Engine
添加阿里云yum源
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0

gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
安装kubeadm/kubelet/kubectl
yum install -y kubelet-1.23.6 kubeadm-1.23.6 kubectl-1.23.6

systemctl enable kubelet

# 配置关闭 Docker 的 cgroups,修改 /etc/docker/daemon.json,加入以下内容
"exec-opts": ["native.cgroupdriver=systemd"]

# 重启 docker
systemctl daemon-reload
systemctl restart docker
3. 部署kubernetes Master
在 Master 节点下执行
kubeadm init \
--apiserver-advertise-address=10.0.0.10 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.23.6 \
--service-cidr=192.168.0.0/20 \
--pod-network-cidr=192.168.0.0/16
安装成功后,复制如下配置并执行
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl get nodes
4. 加入kubernetes Node
分别在 k8s-node1 和 k8s-node2 执行
# 下方命令可以在 k8s master 控制台初始化成功后复制 join 命令

kubeadm join 172.26.120.200:6443 --token 152ar6.aag6akqgoiwjd5j1 \
--discovery-token-ca-cert-hash sha256:d708981fd0179a12cfb2c1062bf5a18a473cd8a5f269b8070d3eec10c70ac446 

# 如果初始化的 token 不小心清空了,可以通过如下命令获取或者重新申请
# 如果 token 已经过期,就重新申请

kubeadm token create

# token 没有过期可以通过如下命令获取
kubeadm token list

# 获取 --discovery-token-ca-cert-hash 值,得到值后需要在前面拼接上 sha256:
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //'
检查结果信息方法:
检查组件:kubectl get componentstatus 或 kubectl get cs
检查pod信息:
[root@k8s-master ~]# kubectl get pods
No resources found in default namespace.
查不到pod信息是因为命名空间问题,集群刚创建的时候不是放在默认namespace,应用:
kubectl get pods -n kube-system
[root@k8s-master ~]# kubectl get pods -n kube-system
NAME                                 READY   STATUS    RESTARTS   AGE
coredns-6d8c4cb4d-gzfgk              0/1     Pending   0          13m
coredns-6d8c4cb4d-mj4pn              0/1     Pending   0          13m
etcd-k8s-master                      1/1     Running   0          13m
kube-apiserver-k8s-master            1/1     Running   0          13m
kube-controller-manager-k8s-master   1/1     Running   0          13m
kube-proxy-55xrt                     1/1     Running   0          10m
kube-proxy-8brl5                     1/1     Running   0          12m
kube-proxy-hlg99                     1/1     Running   0          13m
kube-scheduler-k8s-master            1/1     Running   0          13m
这里发现coredns 是pending状态,这是因为网络原因导致无法下载,需要继续下面步骤5↓
5. 部署CNI网络插件
在 master 节点上执行
## 下载 calico 配置文件,可能会网络超时

curl https://docs.projectcalico.org/manifests/calico.yaml -O


# 修改 calico.yaml 文件中的 CALICO_IPV4POOL_CIDR 配置,修改为与初始化的 cidr 相同

# 修改 IP_AUTODETECTION_METHOD 下的网卡名称

# 删除镜像 docker.io/ 前缀,避免下载过慢导致失败
sed -i 's#docker.io/##g' calico.yaml

#执行这个文件calico.yaml,用kubectl apply ,因为是聚合文件,所有用apply
kubectl apply -f calico.yaml

#再次查看pod ,等待几分钟发现多了pod以及coredns 也好了
kubectl get po -n kube-system

#现在看下新的pod在干什么
5. 测试集群
# 创建部署
kubectl create deployment nginx --image=nginx

# 暴露端口
kubectl expose deployment nginx --port=80 --type=NodePort

# 查看 pod 以及服务信息
kubectl get pod,svc
6. 测试集群
测试集群
# 创建部署
kubectl create deployment nginx --image=nginx

# 暴露端口
kubectl expose deployment nginx --port=80 --type=NodePort

# 查看 pod 以及服务信息
kubectl get pod,svc

  1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.consectetur adipiscing elitconsectetur adipiscing elit 

K8s Pod

On the right hand are reference infomations for create kubernetes resources. resources manifast / official document.


Create Pod using yaml file

pod.yaml
apiVersion: v1 # api 文档版本
kind: Pod #资源对象类型,其他的:Deployment、StatefulSet 
metadata: #Pod的相关元数据,用于描述pod的数据
  name: my-nginx  #pod的名称
  labels: #定义pod标签
    type: app
    version: 1.0.x #自定义
  namespace: 'default' #配置命名空间,默认的是default
spec:  #期望pod 按照这里的描述进行创建
  containers:
  - name: nginx
    image: nginx:1.26.0
    imagePullPolicy: IfNotPresent #指定镜像拉取策略,如果本地没有就拉取远程
    command:
    - nginx
    - -g
    - 'daemon off;' #意为:nginx -g 'daemon off;'
    workingDir: /usr/share/nginx/html #指定容器启动后的工作目录
    ports:
    - name: http #端口名称
      containerPort: 80 #描述容器内要暴露的端口
      protocol: TCP #描述该端口是基于那种协议通信
    env: # 环境变量
      - name: JVM-OPTS #环境名称
        value: '-Xms128m -Xmx128m' #环境变量的值
    resources:
      requests:
        cpu: 100m # cpu一个核心为1000m,这里的100m 为最少0.1个核心
        memory: "128Mi" #最少128兆
      limits:
        cpu: 200m # cpu一个核心为1000m,这里的200m 为最多0.2个核心
        memory: "256Mi" #最多256兆
    #command: ["stress"]
    #args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
  restartPolicy: OnFailure #重启策略:只用失败的情况才会重启
check the pod
kubectl get po
kubectl get po -o wide
kubectl descrbe po my-nginx
Operation_result
[root@k8s-master pods]# kubectl get pod
NAME            READY   STATUS    RESTARTS   AGE
memory-demo-3   1/1     Running   0          4m50s
my-nginx        1/1     Running   0          3m31s
[root@k8s-master pods]# kubectl get pod -o wide
NAME            READY   STATUS    RESTARTS   AGE     IP              NODE        NOMINATED NODE   READINESS GATES
memory-demo-3   1/1     Running   0          4m55s   192.168.36.72   k8s-node1   <none>           <none>
my-nginx        1/1     Running   0          3m36s   192.168.36.73   k8s-node1   <none>           <none>
[root@k8s-master pods]# kubectl describe pod my-nginx
Name:         my-nginx
Namespace:    default
Priority:     0
Node:         k8s-node1/10.0.0.101
Start Time:   Wed, 24 Apr 2024 06:49:02 -0400
Labels:       type=app
              version=1.0.x
Annotations:  cni.projectcalico.org/containerID: bb27fe44a58187928bced7bb6a76234c1717ea8a000d35e8948796a7970b548a
              cni.projectcalico.org/podIP: 192.168.36.73/32
              cni.projectcalico.org/podIPs: 192.168.36.73/32
Status:       Running
IP:           192.168.36.73
IPs:
  IP:  192.168.36.73
Containers:
  nginx:
    Container ID:  docker://71f60f7711b116cf0a6dfa8041381f83c51d40b35ef15f4c0c8756e12ce45c33
    Image:         nginx:1.26.0
    Image ID:      docker-pullable://nginx@sha256:3f28ecedbd787b3ff0a6d56cd4a1b13901acda532c717e3b7351fcc786973d79
    Port:          80/TCP
    Host Port:     0/TCP
    Command:
      nginx
      -g
      daemon off;
    State:          Running
      Started:      Wed, 24 Apr 2024 06:49:03 -0400
    Ready:          True
    Restart Count:  0
    Limits:
      cpu:     200m
      memory:  256Mi
    Requests:
      cpu:     100m
      memory:  128Mi
    Environment:
      JVM-OPTS:  -Xms128m -Xmx128m
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-mkwwb (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  kube-api-access-mkwwb:
    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  3m55s  default-scheduler  Successfully assigned default/my-nginx to k8s-node1
  Normal  Pulled     3m55s  kubelet            Container image "nginx:1.26.0" already present on machine
  Normal  Created    3m55s  kubelet            Created container nginx
  Normal  Started    3m55s  kubelet            Started container nginx
[root@k8s-master pods]# 

Centos Ops

查看linux系统中的信息

查看系统版本

[root@localhost ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)

查看hostname

[root@localhost ~]# hostname
localhost.localdomain
[root@localhost ~]# cat /etc/hostname
localhost.localdomain

修改主机名hostname

临时修改

通过hostname $主机名来修改,重启后就会恢复回去

永久修改

通过hostnamectl set-hostname $主机名来修改

hostnamectl命令,该命令是centos7后才引入的.

在CentOS7中有三种定义的主机名:
-  静态的(static): 也称为内核主机名,是系统在启动时从/etc/hostname内自动初始化的主机名;
-  瞬态的(transient):是在系统运行时临时分配的主机名;
-  灵活的(pretty):允许使用特殊字符的主机名
[root@localhost ~]# hostnamectl set-hostname k8s-master
[root@localhost ~]# cat /etc/hostname #注:设置静态主机名只对新连接的会话立即生效,对于当前连接则不生效,需要重新连接即可查看效果
k8s-master  
[root@k8s-master ~]# cat /etc/hostname  #这里是重连后的效果
k8s-master

yum命令

建立yum仓库缓存

我们在更新yum源或者出现配置yum源之后,通常都会使用yum makecache 生成索引缓存索引提供搜索安装速度,索引缓存存储位置: /var/cache/yum/
yum makecache fast命令是将软件包信息提前在本地索引缓存,用来提高搜索安装软件的速度,建议执行这个命令可以提升yum安装的速度。

yum makecache #[fast]

清理yum所有缓存

yum 会把下载的软件包和header存储在cache中而不自动删除。如果觉得占用磁盘空间,可以使用yum clean指令清除索引缓存和下载包的缓存。

yum clean all

verify

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor massa, nec semper lorem quam in massa.

[root@localhost 7]#  cd /var/cache/yum/ 
[root@localhost 7]#  du -sh *
112M    base
8.0K    CentOS-Base
8.0K    docker-ce-stable
163M    epel
4.2M    extras
12K gitlab_gitlab-ce
12K gitlab_gitlab-ce-source
8.0K    mysql56-community
8.0K    mysql-connectors-community
8.0K    mysql-tools-community
8.0K    nginx
0   onlyoffice
4.0K    timedhosts
0   timedhosts.22657
0   timedhosts.txt
114M    updates
0   zabbix
0   zabbix-non-supported

scp命令

上传 通过网络传输文件到目的地

scp *.repo root@k8s-master:/etc/yum.repos.d/
graph LR
  A[Start] --> B{Error?};
  B -->|Yes| C[Hmm...];
  C --> D[Debug];
  D --> B;
  B ---->|No| E[Yay!];
  B ------> AAA;

Lorem ipsum1 dolor sit amet, consectetur adipiscing elit.[^2]

bacd

asd asdasd

Linux tail 命令

tail [参数] [文件]  

参数

  • -f 循环读取
  • -q 不显示处理信息
  • -v 显示详细的处理信息
  • -c<数目> 显示的字节数
  • -n<行数> 显示文件的尾部 n 行内容
  • --pid=PID 与-f合用,表示在进程ID,PID死掉之后结束
  • -q, --quiet, --silent 从不输出给出文件名的首部
  • -s, --sleep-interval=S 与-f合用,表示在每次反复的间隔休眠S秒

Usage

要显示 notes.log 文件的最后 10 行,请输入以下命令:

tail notes.log         # 默认显示最后 10 行
此命令显示 notes.log 文件的最后 10 行。当将某些行添加至 notes.log 文件时,tail 命令会继续显示这些行。 显示一直继续,直到您按下(Ctrl-C)组合键停止显示。

显示文件 notes.log 的内容,从第 20 行至文件末尾:

tail -n +20 notes.log

显示文件 notes.log 的最后 10 个字符:

tail -c 10 notes.log


  1. Lorem ipsum dolor sit amet, consectetur adipiscing elit. 

CENTOS7.* SSH/Network

配置network网卡信息

编辑网络接口配置文件

vi /etc/sysconfig/network-scripts/ifcfg-eth0
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
IPADDR=10.0.0.10
PREFIX=24
GAITEWAY=10.0.0.1
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=no
IPV6_AUTOCONF=no
IPV6_DEFROUTE=no
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=eth0
UUID=3d02essf7-7de0-4d3f-8dc1-f32db784aab5
DEVICE=eth0
ONBOOT=yes

配置ssh

编辑ssh配置文件

vi /etc/ssh/sshd_config 
找到下面2项,把 no 改为 yes
PermitRootLogin yes
PasswordAuthentication yes
The range() function is used to generate a sequence of numbers.

k8s Resources Classifcation

k8s资源的分类

元空间、集群、命名空间 alt text

简单的分类为以下几种资源对象:

类别 名称
资源对象 Pod、ReplicaSet、ReplicationController、Deployment、StatefulSet、DaemonSet、Job、CronJob、HorizontalPodAutoscaling、Node、Namespace、Service、Ingress、Label、CustomResourceDefinition
存储对象 Volume、PersistentVolume、Secret、ConfigMap
策略对象 SecurityContext、ResourceQuota、LimitRange
身份对象 ServiceAccount、Role、ClusterRole

K8SK8SResourcesManifest

参数名 类型 字段说明
apiVersion String K8S APl 的版本,可以用 kubectl api versions 命令查询
kind String yam 文件定义的资源类型和角色
metadata Object 元数据对象,下面是它的属性
metadata.name String 元数据对象的名字,比如 pod 的名字
metadata.namespace String 元数据对象的命名空间
Spec Object 详细定义对象
spec.containers[] list 定义 Spec 对象的容器列表
spec.containers[].name String 为列表中的某个容器定义名称
spec.containers[].image String 为列表中的某个容器定义需要的镜像名称
spec.containers[].imagePullPolicy string 定义镜像拉取策略,有 Always、Never、IfNotPresent 三个值可选
- Always(默认):意思是每次都尝试重新拉取镜像
- Never:表示仅适用本地镜像
- IfNotPresent:如果本地有镜像就使用本地镜像,没有就拉取在线镜像。
spec.containers[].command[] list 指定容器启动命令,因为是数组可以指定多个,不指定则使用镜像打包时使用的启动命令。
spec.containers[].args[] list 指定容器启动命令参数,因为是数组可以指定多个。
spec.containers[].workingDir string 指定容器的工作目录
spec.containers[].volumeMounts[] list 指定容器内部的存储卷配置
spec.containers[].volumeMounts[].name string 指定可以被容器挂载的存储卷的名称
spec.containers[].volumeMounts[].mountPath string 指定可以被容器挂载的存储卷的路径
spec.containers[].volumeMounts[].readOnly string 设置存储卷路径的读写模式,ture 或者 false,默认是读写模式
spec.containers[].ports[] list 指定容器需要用到的端口列表
spec.containers[].ports[].name string 指定端口的名称
spec.containers[].ports[].containerPort string 指定容器需要监听的端口号
spec.containers[].ports[].hostPort string 指定容器所在主机需要监听的端口号,默认跟上面 containerPort 相同,注意设置了 hostPort 同一台主机无法启动该容器的相同副本(因为主机的端口号不能相同,这样会冲突)
spec.containers[].ports[].protocol string 指定端口协议,支持 TCP 和 UDP,默认值为 TCP
spec.containers[].env[] list 指定容器运行前需设置的环境变量列表
spec.containers[].env[].name string 指定环境变量名称
spec.containers[].env[].value string 指定环境变量值
spec.containers[].resources Object 指定资源限制和资源请求的值(这里开始就是设置容器的资源上限)
spec.containers[].resources.limits Object 指定设置容器运行时资源的运行上限
spec.containers[].resources.limits.cpu string 指定 CPU 的限制,单位为 Core 数,将用于 docker run –cpu-shares 参数
spec.containers[].resources.limits.memory string 指定 mem 内存的限制,单位为 MIB、GiB
spec.containers[].resources.requests Object 指定容器启动和调度时的限制设置
spec.containers[].resources.requests.cpu string CPU请求,单位为core数,容器启动时初始化可用数量
spec.containers[].resources.requests.memory string 内存请求,单位为MIB、GiB,容器启动的初始化可用数量
spec.restartPolicy string 定义 pod 的重启策略,可选值为 Always、OnFailure、Never,默认值为 Always。
- Always:pod 一旦终止运行,则无论容器是如何终止的,kubelet 服务都将重启它。
- OnFailure:只有 pod 以非零退出码终止时,kubelet 才会重启该容器。如果容器正常结束(退出码为0),则 kubectl 将不会重启它。
- Never:Pod 终止后,kubelet 将退出码报告给 master,不会重启该 pod
spec.nodeSelector Object 定义 Node 的 label 过滤标签,以 key:value 格式指定
spec.imagePullSecrets Object 定义 pull 镜像时使用 secret 名称,以 name:secretkey 格式指定
spec.hostNetwork Boolean 定义是否使用主机网络模式,默认值为 false。设置 true 表示使用宿主机网络,不使用 docker 网桥,同时设置了 true将无法在同一台宿主机上启动第二个副本

对象

以下列举的内容都是 Kubernetes 中的对象(Object),这些对象都可以在 YAML 文件中作为一种 API 类型来配置。

  • Pod
  • Node
  • Namespace
  • Service
  • Volume
  • PersistentVolume
  • Deployment
  • Secret
  • StatefulSet
  • DaemonSet
  • ServiceAccount
  • ReplicationController
  • ReplicaSet
  • Job
  • CronJob
  • SecurityContext
  • ResourceQuota
  • LimitRange
  • HorizontalPodAutoscaling
  • Ingress
  • ConfigMap
  • Label
  • CustomResourceDefinition
  • Role
  • ClusterRole