基于模板创建Job

基于一个公共的模板运行多个Jobs。 你可以用这种方法来并行执行批处理任务。

使用 Shell 脚本

创建 Job 模板(job-tmpl.yaml)

apiVersion: batch/v1
kind: Job
metadata:
  name: process-item-$ITEM
  labels:
    jobgroup: jobexample
spec:
  template:
    metadata:
      name: jobexample
      labels:
        jobgroup: jobexample
    spec:
      containers:
      - name: c
        image: busybox
        command: ["sh", "-c", "echo Processing item $ITEM && sleep 5"]
      restartPolicy: Never

$ITEM 是占位符,在使用的时候进行替换。

基于模板生成多个 Job YAML

mkdir ./jobs
for i in apple banana cherry
do
  cat job-tmpl.yaml | sed "s/\$ITEM/$i/" > ./jobs/job-$i.yaml
done

查看 jobs 目录,可以看到下面的结果。

Kubernetes中的Job和CronJob

Job

用于处理离线业务的,运行完成后就终止执行。

运行一个 Pod 对象

编写 Job 的 YAML 文件(job-pi.yaml)

bc 命令是 Linux 里的“计算器”;-l 表示使用标准数学库;a(1) 是调用数学库中的 arctangent 函数,计算 atan(1)。

tan(π/4) = 1。所以,4*atan(1)正好就是π,也就是 3.1415926…。

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: pi
        image: alpine
        command: ["sh", "-c", "echo 'scale=6000; 4*a(1)' | bc -l"]
  • restartPolicy: Pod 内所有容器的重启策略。对于 Job 重启策略只能是 OnFailure 和 Never,默认是 Always。
    • OnFailure
    • Never
    • Always(default)

创建 Job 对象

$ kubectl apply -f job-pi.yaml 
job.batch/pi created

Kubernetes中的DaemonSet

DaemonSet

确保每个节点运行一个 Pod。

使用场景

  • 日志收集
  • 资源监控
  • 网络代理

编写 DaemonSet 的YAML文件(kubia-ds.yaml)

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: kubia
spec:
  selector:
    matchLabels:
      app: kubia
  template:
    metadata:
      labels:
        app: kubia 
    spec:
      containers:
      - name: kubia 
        image: wangjunjian/kubia:latest 
        ports:
        - containerPort: 8080

创建 DaemonSet 对象

$ kubectl apply -f kubia-ds.yaml 
daemonset.apps/kubia created

查看 DaemonSet 对象

ds 是 DaemonSet 的缩写

$ kubectl get ds
NAME    DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
kubia   3         3         2       3            2           <none>          22s

查看 Pod 对象 $ kubectl get pods -o wide NAME READY STATUS RESTARTS

Kubernetes中的ReplicationController和ReplicaSet

ReplicationController

保证 Pod 对象始终处于期望的运行状态。不管 Pod 因何种原因消失(节点从集群消失或pod从节点中逐出)。

控制器的协调流程

LOOP

  1. 通过标签选择器匹配 Pod
  2. 比较匹配的数量与期望的副本数量
  • 少了。使用当前的模板创建 Pod
  • 多了。删除超出数量的 Pod
  • 等于。

ReplicationController 的三个主要部分

  • selector, 标签选择器
  • replicas, 副本个数
  • template, Pod 模板

编写 ReplicationController 的YAML文件(kubia-rc.yaml) apiVersion: v1 kind: ReplicationController metadata: name: kubia spec: selector: app: kubia replicas: 2 template: metadata: labels: app: kubia spec: containers: - name: kubia image: wangjunjian/kubia:latest ports: - containerPort: 8080 ★ 可以不指定标签选择器(selector),它会自动根据 Pod 模板中的标签设置。

Kubernetes中的名字空间

名字空间

名字空间将对象分割成独立的组,为对象名字提供了作用域,名字在不同的名字空间可以是相同的。名字空间对正在运行的对象不提供任何隔离,名字空间之间是否提供网络隔离取决于 Kubernetes 所使用的网络解决方案。

查看当前集群中的所有名字空间

$ kubectl get namespaces 
NAME                   STATUS   AGE
default                Active   379d
kube-node-lease        Active   379d
kube-public            Active   379d
kube-system            Active   379d
kubernetes-dashboard   Active   377d

创建名字空间

  • 使用命令
$ kubectl create namespace kubia
namespace/kubia created
  • 编写 YAML 文件(kubia-namespace.yaml)
apiVersion: v1
kind: Namespace
metadata:
  name: kubia
$ kubectl apply -f kubia-namespace.yaml 
namespace/kubia created

查看新创建的名字空间,ns 是 namespace 的缩写。

$ kubectl get ns kubia
NAME    STATUS   AGE
kubia   Active   35s

Kubernetes中的注解

注解

注解也是键值对,和标签类似,但没有对象的选择器来进行分组筛选,它可以容纳更多的内容(总共不超过256KB),主要用于工具的使用。Kubernetes 会将一些注解自动添加到对象。

增加(key=value)

添加域名(gouchicao.com)前缀这种格式的注解键是避免键冲突的一个好方法。

$ kubectl annotate pod kubia-manual gouchicao.com/someannotation="test"
pod/kubia-manual annotated

需要增加多个注解只需要使用空格进行分隔即可。

$ kubectl annotate pod kubia-manual key1=value1 key2=value2

查看 获取完整的 YAML 描述(-o yaml) $ kubectl get pod kubia-manual -o yaml apiVersion: v1 kind: Pod metadata: annotations: gouchicao.com/someannotation: test kubectl.kubernetes.

Kubernetes中的标签和标签选择器

标签

标签是键值对的形式,用于组织 Kubernetes 资源,为对象进行分组。只要标签的 key 在资源内是唯一的,一个资源便可以拥有多个标签。

通过添加两个标签将 Pod 组织为两个维度(基于应用的横向维度和基于版本的纵向维度)

编写带标签的 Pod YAML文件(kubia-manual-labels.yaml)

apiVersion: v1
kind: Pod
metadata:
  name: kubia-manual-v2
  labels:
    app: sc
    rel: stable
spec:
  containers:
  - image: wangjunjian/kubia
    name: kubia
    ports:
    - containerPort: 8080
      protocol: TCP

创建带标签的 Pod

$ kubectl apply -f kubia-manual-labels.yaml
pod/kubia-manual-v2 created

查看 Pod 的标签(--show-labels) $ kubectl get pods --show-labels NAME READY STATUS RESTARTS AGE LABELS kubia-864465c9d-744qc 1/1 Running 0 5d3h app=kubia,pod-template-hash=864465c9d

通过端口转发连接Pod

通过端口转发(port-forward)可以连接到 Pod,方便测试和调试服务。

创建 Pod

编写 Pod YAML文件(kubia-manual.yaml)

apiVersion: v1
kind: Pod
metadata:
  name: kubia-manual
spec:
  containers:
  - image: wangjunjian/kubia
    name: kubia
    ports:
    - containerPort: 8080
      protocol: TCP

创建 Pod

$ kubectl apply -f kubia-manual.yaml 
pod/kubia-manual created

查看 Pod

$ kubectl get pod kubia-manual
NAME           READY   STATUS    RESTARTS   AGE
kubia-manual   1/1     Running   0          77s

查看 Pod 的完整描述

  • YAML 格式
$ kubectl get pod kubia-manual -o yaml
  • JSON 格式
$ kubectl get pod kubia-manual -o json

日志查看

logs 是查看容器的日志,Pod 只有一个容器时,可以忽略容器名。

$ kubectl logs kubia-manual 
Kubia server starting...

Kubernetes API

Kubernetes 对象

在 Kubernetes 系统中,Kubernetes 对象是持久化的实体。 Kubernetes 使用这些实体去表示整个集群的状态。

  • apiVersion - 创建该对象所使用的 Kubernetes API 的版本
  • kind - 想要创建的对象的类别
  • metadata - 帮助唯一性标识对象的一些数据,包括一个 name 字符串、UID 和可选的 namespace
  • spec - 对象规约,描述你希望对象所具有的特征:期望状态(Desired State)。
  • status - 对象状态,描述了对象的 当前状态(Current State),它是由 Kubernetes 系统和组件 设置并更新的。在任何时刻,Kubernetes 控制平面 都一直积极地管理着对象的实际状态,以使之与期望状态相匹配。

查看 Pod 对象的完整描述 $ kubectl get pod kubia-864465c9d-744qc -o yaml apiVersion: v1 kind: Pod metadata: creationTimestamp: "2021-06-24T00:13:37Z" generateName: kubia-864465c9d- labels: app: kubia pod-template-hash: 864465c9d nam

在Kubernetes上运行第一个应用

基于Node构建应用

app.js

const http = require('http');
const os = require('os');

console.log("Kubia server starting...");

var handler = function(request, response) {
  console.log("Received request from " + request.connection.remoteAddress);
  response.writeHead(200);
  response.end("You've hit " + os.hostname() + "\n");
};

var www = http.createServer(handler);
www.listen(8080);

Dockerfile

FROM node:16-slim
ADD app.js /app.js
ENTRYPOINT ["node", "app.js"]

构建

docker build -t wangjunjian/kubia .

运行 docker run -d -p 8080:8080 wangjun

Kubernetes中删除节点

查看集群节点

kubectl get nodes
NAME   STATUS   ROLES    AGE    VERSION
gpu1   Ready    <none>   227d   v1.18.3
gpu2   Ready    <none>   31d    v1.18.3
ln1    Ready    master   370d   v1.18.3
ln2    Ready    <none>   370d   v1.18.3
ln3    Ready    <none>   370d   v1.18.3

驱逐节点 kubectl drain gpu2 --delete-local-data --ignore-daemonsets --force node/gpu2 already cordoned WARNING: ignoring DaemonSet-managed Pods: default/dcgm-exporter-1617245566-6gvdw, kube-system/kube-proxy-jhfh5, kube-system/nvidia-device-plugin-daemonset-spflp, kube-system/weave-net-ktsbp, monitoring/kube-prometheus-stack-prometheus-node-exporter-dpnzx, rook-ceph/csi-ce

Kubernetes集群证书过期

证书一年过期了

kubectl get nodes
Unable to connect to the server: x509: certificate has expired or is not yet valid

查看API服务器的证书日期

  • 方法1
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text|grep -A2 'Validity'
        Validity
            Not Before: Jun 16 06:09:07 2020 GMT
            Not After : Jun 16 06:09:07 2021 GMT
  • 方法2
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text|grep ' Not '
            Not Before: Jun 16 06:09:07 2020 GMT
            Not After : Jun 16 06:09:07 2021 GMT

重新配置证书 sudo kubeadm alpha certs renew all [renew] Reading configuration from the cluster...