[toc]

POD资源创建

资源清单数据类型

  • string

    • 字符串
  • boolean

    • 布尔值

    • 示例

      1
      2
      True/Yes
      False/No
  • integer

    • 整型
  • [ ]

    • 列表类型

    • 示例1

      1
      ['苹果','香蕉','桃子']
    • 示例2

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      ansible:
      yum:
      name:
      - nginx
      - mysql-server
      - php-fpm
      k8s:
      containers:
      - name:
      image:
      imagePullPolicy:
      - name:
      image:
      imagePullPolicy:
  • object

    • 字典类型

    • 示例

      1
      2
      3
      name: zls
      age: 18
      app: nginx

命令行创建POD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 语法格式
kubectl create [控制器名称] [POD名称] [--image=指定镜像]

# 创建nginx的pod(根据资源自动指定node节点)
kubectl create deployment nginx --image=nginx:alpine

# 连接进入容器
kubectl exec -it aaa -- /bin/sh

# 在对应node节点上查看启动的pod(见下图1)
docker ps
## 启动POD会启动自定义的容器和一个根容器

# 查看pod并输出详细信息(见下图2)
kubectl get pod -o wide
  • 图1

    image-20230611203235351

  • 图2

    image-20230611203214472

资源清单创建POD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# Kubernetes API 参考文档
http://k8s.driverzeng.com/v1.19/

# 将pod输出成yaml格式
kubectl get pod aaa -o yaml

# 查看yaml格式的pod启动文件
cat nginx.yaml
apiVersion: v1 # api接口的版本
kind: Pod # kind指定资源:POD
metadata: # 资源的元数据[资源名|资源标签|...]
name: aaa # 资源名字
labels: # 资源标签
mem: 16g # 标签名: 标签值
spec: # 容器相关信息
containers: # 指定容器信息
- image: nginx:alpine # 指定容器镜像
imagePullPolicy: IfNotPresent # 镜像拉取规则
name: abc-nginx # 容器名称

# 使用资源清单创建名称空间
vim nginx.yaml
apiVersion: v1
kind: Namespace
metadata:
name: kube-zls

# 应用资源清单
kubectl apply -f nginx.yaml
## 语法选项
kubectl create -f nginx.yaml
- create:是创建,没有创建过的情况下,使用create
- apply:是应用,没创建过的情况下,会创建,创建过的情况下,会更新资源内容

# 修改资源清单
kubectl edit pod aaa

使用资源清单启动MySQL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 编辑yaml格式的pod启动文件
vim mysql-pod.yaml
apiVersion: "v1"
kind: "Pod"
metadata:
name: mysql
namespace: test-mysql
labels:
name: mysql_pod
spec:
containers:
- name: mysql
image: mysql:latest
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: "123"
- name: MYSQL_DATABASE
value: "wp_data"
- name: MYSQL_USER
value: "wp"
- name: MYSQL_PASSWORD
value: "123"
args:
- --character-set-server=utf8
--collation-server=utf8_bin

## 镜像拉取规则
imagePullPolicy: IfNotPresent
- Always:如果latest镜像更新,那么每次执行资源清单都会重新拉最新镜像
- Never:永远都不拉镜像,用本地镜像
- IfNotPresent:如果镜像本地存在,则不拉取,如果镜像本地不存在,则拉取
## 指定字符集
--character-set-server=utf8
--collation-server=utf8_bin

# 应用资源清单
kubectl apply -f mysql-pod.yaml
pod/mysql-pod created

重新认识POD

image-20230611195011781

网络共享

  • POD内的容器使用Container模式共享根容器的网络
  • 容器看到的网络设备信息和根容器完全相同
  • POD内的多个容器可以使用localhost进行网络通讯
  • POD内的多个容器不能绑定相同的端口
  • POD的生命周期和根容器一样,如果根容器退出了,POD就退出了
  • 默认情况下,同一个POD中容器之间的文件系统不共享(需要映射)

文件共享

  • 默认情况下一个POD内的容器文件系统是互相隔离的
  • 如果想让一个POD容器共享文件那么只需要定义一个Volume,然后两个容器分别挂载到这个Volume中
  • 即:共享存储

image-20230611195033682

一个资源清单启动两个容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# 编辑启动pod的yaml文件
vim nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx-container1
image: nginx:alpine
imagePullPolicy: IfNotPresent

- name: nginx-container2
image: nginx:alpine
imagePullPolicy: IfNotPresent

# 应用资源清单
kubectl apply -f nginx-pod.yaml

# 查看pod
kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-pod 1/2 CrashLoopBackOff 4 2m35s
## 发现有一个容器无法启动

# 排错:
## 查看pod创建流程详细信息
kubectl describe pod nginx-pod
## 查看容器日志
kubectl logs nginx-pod nginx-container1
kubectl logs nginx-pod nginx-container2
2023/06/09 04:05:38 [emerg] 1#1: bind() to [::]:80 failed (98: Address in use)
nginx: [emerg] bind() to [::]:80 failed (98: Address in use)
## 一个pod有多个容器时,指定容器连接
kubectl exec -it nginx-pod -c nginx-container2 -- /bin/sh
kubectl exec -it nginx-pod -c nginx-container1 -- /bin/sh
## 两个容器端口相同无法启动

# 正确示例
apiVersion: v1
kind: Pod
metadata:
name: nginx-db-pod
spec:
containers:
- name: nginx-container1
image: nginx:alpine
imagePullPolicy: IfNotPresent

- name: mysql-container-test
image: mysql:5.7
imagePullPolicy: IfNotPresent
env:
- name: MYSQL_ROOT_PASSWORD
value: '123'
- name: MYSQL_DATABASE
value: 'wordpres'
- name: MYSQL_USER
value: 'wp_user'
- name: MYSQL_PASSWORD
value: '123'
args:
- --character-set-server=utf8
--collation-server=utf8_bin

# 查看pod启动的容器状态
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-db-pod 2/2 Running 0 24s 10.2.1.10 k8s03 <none> <none>

POD示例:nginx-mysql

需求

  • 启动一个POD
  • 启动nginx容器
    • 映射站点目录的路径:/usr/share/nginx/html
    • 映射宿主机的路径:/data/nginx
  • 启动MySQL容器
    • 映射数据目录的路径:/var/lib/mysql
    • 映射宿主机的路径:/data/mysql

创建资源清单

  • 创建部署nginx和MySQL的资源清单

    • 编辑资源清单

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      vim nginx-mysql.yaml
      apiVersion: v1
      kind: Pod
      metadata:
      name: nginx-db-pod
      spec:
      containers:
      - name: nginx-container
      image: nginx:alpine
      imagePullPolicy: IfNotPresent

      - name: mysql-container
      image: mysql:5.7
      imagePullPolicy: IfNotPresent
      env:
      - name: MYSQL_ROOT_PASSWORD
      value: '123'
  • 使用”hostPath”挂载”nginx”数据目录

    • “hostPath”挂载图示

      image-20230612194929258

    • 编辑资源清单

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      vim nginx-mysql.yaml
      apiVersion: v1
      kind: Pod
      metadata:
      name: nginx-db-pod
      spec:
      volumes:
      - name: codedir
      hostPath:
      path: /data/nginx

      containers:
      - name: nginx-container
      image: nginx:alpine
      imagePullPolicy: IfNotPresent
      volumeMounts:
      - mountPath: /usr/share/nginx/html/
      name: codedir

      - name: mysql-container
      image: mysql:5.7
      imagePullPolicy: IfNotPresent
      env:
      - name: MYSQL_ROOT_PASSWORD
      value: '123'
      volumeMounts:
      - mountPath: /usr/share/nginx/html/
      name: codedir
  • 使用”emptyDir”临时挂载”nginx”数据目录

    • “emptyDir”挂载图示

      image-20230612195005020

    • 编辑资源清单

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      emptyDir{}
      apiVersion: v1
      kind: Pod
      metadata:
      name: nginx-db-pod
      spec:
      volumes:
      - name: codedir
      emptyDir: {}

      containers:
      - name: nginx-container
      image: nginx:alpine
      imagePullPolicy: IfNotPresent
      volumeMounts:
      - mountPath: /usr/share/nginx/html/
      name: codedir

      - name: mysql-container
      image: mysql:5.7
      imagePullPolicy: IfNotPresent
      env:
      - name: MYSQL_ROOT_PASSWORD
      value: '123'
      volumeMounts:
      - mountPath: /usr/share/nginx/html/
      name: codedir
  • 最终资源清单

    • 编辑资源清单

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      apiVersion: v1
      kind: Pod
      metadata:
      name: nginx-db
      spec:
      volumes:
      - name: codedir
      hostPath:
      path: /data/nginx
      - name: dbdata
      hostPath:
      path: /data/mysql
      containers:
      - name: nginx-container
      image: nginx:alpine
      imagePullPolicy: IfNotPresent
      volumeMounts:
      - mountPath: /usr/share/nginx/html
      name: codedir
      - mountPath: /var/lib/mysql
      name: dbdata

      - name: mysql-container
      image: mysql:5.7
      imagePullPolicy: IfNotPresent
      env:
      - name: MYSQL_ROOT_PASSWORD
      value: '123'
      volumeMounts:
      - mountPath: /var/lib/mysql
      name: dbdata
      - mountPath: /usr/share/nginx/html
      name: codedir

POD的生命周期

结构图示

  • pod各动作下的状态图示

    image-20230612200056842

  • pod运行结构图示

    image-20230612200106994

初始化容器”init container”

初始化容器的概念

  • 初始化容器是指,在主容器启动之前,我们可以让他做一些准备工作。
  • 使用较小的容器可以减少执行的时间,比如使用”busybox”容器
  • 比如:
    1. 两个容器做了共享存储,那么我们可以让它先启动一个容器,来对目录进行更改用户和授权
    2. 容器需要连接数据库,那么可以让初始化容器检测数据库是否可以正常连接,如果可以再启动主容器

示例:初始化容器准备网页代码

  • 列表类型示例1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    apiVersion: v1
    kind: Pod
    metadata:
    name: init-nginx-pod
    spec:
    volumes:
    - name: init-dir
    emptyDir: {}

    initContainers:
    - name: init
    image: busybox
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: init-dir
    mountPath: /data/nginx
    args:
    - '/bin/sh'
    - '-c'
    - '/bin/echo test_k8s_init > /data/nginx/index.html'


    containers:
    - name: nginx-c
    image: nginx:alpine
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - mountPath: /usr/share/nginx/html
    name: init-dir
  • 列表类型实例2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    apiVersion: v1
    kind: Pod
    metadata:
    name: init-nginx-pod
    spec:
    volumes:
    - name: init-dir
    emptyDir: {}

    initContainers:
    - name: init
    image: busybox
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: init-dir
    mountPath: /data/nginx
    args: ['/bin/sh','-c','/bin/echo testxxxxxxxxxxxxxxxxxxxxxxxx > /data/nginx/index.html']

    containers:
    - name: nginx-c
    image: nginx:alpine
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - mountPath: /usr/share/nginx/html
    name: init-dir
  • 挂载结构图示

    image-20230612201628809

POD钩子(hook)web hook

hook的概念

  • hook
    • Pre:在….之前
    • Post:在….之后
  • PostStart
    • 启动钩子,在容器启动创建后,立即执行,但时间不能太长,否则容器不会是running状态
  • PreStop
    • 在容器停止前,执行一些命令,主要用于优雅关闭程序

PostStart启动钩子(启动之后的操作)

  • PostStart语法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    exec:        # 执行命令
    command: # 要执行的命令
    httpGet: # 发送HTTP请求(检测页面健康状态)
    host: # blog.zls.com
    path: # /index.html
    port: # 80
    tcpSocket: # 建立TCP连接
    host: # 10.0.0.51
    port: # 3306
  • 启动钩子exec示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    apiVersion: v1
    kind: Pod
    metadata:
    name: init-nginx-pod
    spec:
    containers:
    - name: nginx-c
    image: nginx:alpine
    imagePullPolicy: IfNotPresent
    lifecycle:
    postStart:
    exec:
    command: ['/bin/sh','-c','/bin/echo test_POST_start > /usr/share/nginx/html/index.html']

PreStop停止钩子(停止之前的操作)

  • PreStop语法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    exec:        # 执行命令
    command: # 要执行的命令
    httpGet: # 发送HTTP请求(检测页面健康状态)
    host: # blog.zls.com
    path: # /index.html
    port: # 80
    tcpSocket: # 建立TCP连接
    host: # 10.0.0.51
    port: # 3306
  • 停止钩子exec示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    apiVersion: v1
    kind: Pod
    metadata:
    name: pre-nginx-pod
    spec:
    volumes:
    - name: test
    hostPath:
    path: /data/nginx
    containers:
    - name: nginx-pre
    image: nginx:alpine
    imagePullPolicy: IfNotPresent
    lifecycle:
    preStop:
    exec:
    command: ['/bin/sh','-c','/bin/echo bye > /tmp/1.txt']
    volumeMounts:
    - name: test
    mountPath: /tmp/

POD探针

探针概念

  • 存活性探针
    • 简单来说就是用来检测容器的应用程序是否还正常工作,如果应用程序不正常,即使容器还活着也没有意义了
    • 所以这时候就可以使用存活探针来探测,如果应用程序不正常,就重启POD。
  • 就绪性探针
    • 有时候我们Pod本身已经起来了,但是pod的容器还没有完全准备好对外提供服务,那么这时候流量进来就会造成请求失败的情况出现
    • 针对此情况k8s有一种就绪探针,作用就是让k8s知道你的Pod内应用是否准备好为请求提供服务。只有就绪探针ok了才会把流量转发到pod上。

存活性探针

  • 存活性探针语法(在containers下一级)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    livenessprobe:
    exec: # 执行命令
    command: # [需要执行的命令]
    httpGet:
    host: # www.chenlin.cloud
    path: # /index.html
    port: # 80
    tcpSocket:
    port: # 3306
    timeoutSeconds: # 超时时间
    initialDelaySeconds: # 第一次执行执行存活探针,需要等待的时间(等待服务启动的时间)
    failureThreshold: # 检测失败的次数(达到指定次数后,才重启POD)
    periodSeconds: # 执行探针间隔时间
    successThreshold: # 检测成功的次数
  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    apiVersion: v1
    kind: Pod
    metadata:
    name: live-nginx-pod
    spec:
    volumes:
    - name: live-nginx
    hostPath:
    path: /root/nginx

    containers:
    - name: nginx-c
    image: nginx:alpine
    imagePullPolicy: IfNotPresent
    lifecycle:
    postStart:
    exec:
    command: ['/bin/sh','-c','/bin/echo test live > /usr/share/nginx/html/index.html']
    livenessProbe:
    httpGet:
    path: /index.html
    port: 80
    timeoutSeconds: 20
    initialDelaySeconds: 3
    failureThreshold: 3
    periodSeconds: 1
    volumeMounts:
    - name: live-nginx
    mountPath: /usr/share/nginx/html

就绪性探针

  • 就绪性探针语法(在containers下一级)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    readnessprobe:
    exec: # 执行命令
    command: # [需要执行的命令]
    httpGet:
    host: # www.chenlin.cloud
    path: # /index.html
    port: # 80
    tcpSocket:
    port: # 3306
    timeoutSeconds: # 超时时间
    initialDelaySeconds: # 第一次执行执行存活探针,需要等待的时间(等待服务启动的时间)
    failureThreshold: # 检测失败的次数(达到指定次数后,才重启POD)
    periodSeconds: # 执行探针间隔时间
    successThreshold: # 检测成功的次数
  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    apiVersion: v1
    kind: Pod
    metadata:
    name: read-nginx-pod
    spec:
    volumes:
    - name: read-nginx
    hostPath:
    path: /root/nginx

    containers:
    - name: nginx-c
    image: nginx:alpine
    imagePullPolicy: IfNotPresent
    lifecycle:
    postStart:
    exec:
    command: ['/bin/sh','-c','/bin/echo test live > /usr/share/nginx/html/index.html']

    livenessProbe:
    httpGet:
    path: /index.html
    port: 80
    timeoutSeconds: 20
    initialDelaySeconds: 3
    failureThreshold: 3
    periodSeconds: 1

    readinessProbe:
    tcpSocket:
    port: 3306
    timeoutSeconds: 20
    initialDelaySeconds: 3
    failureThreshold: 3
    periodSeconds: 1

    volumeMounts:
    - name: read-nginx
    mountPath: /usr/share/nginx/html

拓展:启动自动化代码上线平台的POD

需求

  • 启动gitlab
  • 启动jenkins
  • 启动在一个pod中

方案

  • POD资源清单
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
apiVersion: v1
kind: Pod
metadata:
name: gitlab-pod
spec:
volumes:
- name: gitlab-conf
hostPath:
path: /data/gitlab/config
- name: gitlab-log
hostPath:
path: /data/gitlab/logs
- name: gitlab-data
hostPath:
path: /data/gitlab/data
- name: docker-conf
hostPath:
path: /etc/docker/daemon.json
- name: jenkins-data
hostPath:
path: /data/jenkins
- name: docker-cmd
hostPath:
path: /usr/bin/docker
- name: docker-sock
hostPath:
path: /var/run/docker.sock

containers:
- name: gitlab-c
image: gitlab/gitlab-ce:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: gitlab-conf
mountPath: /etc/gitlab
- name: gitlab-log
mountPath: /var/log/gitlab
- name: gitlab-data
mountPath: /var/opt/data

- name: jenkins-c
image: jenkins/jenkins
imagePullPolicy: IfNotPresent
volumeMounts:
- name: docker-conf
mountPath: /etc/docker/daemon.json
- name: jenkins-data
mountPath: /var/jenkins_home
- name: docker-cmd
mountPath: /usr/bin/docker
- name: docker-sock
mountPath: /var/run/docker.sock