第一章:Kubernetes 对象(Kubernetes Objects)

1.1 什么是 Kubernetes 的对象?

  • 官网
  • Kubernetes 里面操作的资源实体,就是 Kubernetes 的对象,可以使用 yaml 来声明,然后让 Kubernetes 根据 yaml 的声明创建出这个对象。
  • 操作 Kubernetes 对象,无论是创建、修改还是删除,都需要使用 Kubernetes 的 API 。如:当使用 kubectl 命令行的时候,CLI 会执行必要的 Kubernetes API 调用。
  • Kubernetes 对象指的是 Kubernetes 系统的持久化实体,所有的这些 Kubernetes 镀锡,就代表了当前集群中的实际情况。常规的应用中,我们将应用程序产生的数据存放在数据库中;同理,Kubernetes 将其数据以 Kubernetes 对象的形式通过 api-server 存储在 etcd 中。具体来说,这些数据(Kubernetes 对象)描述了:
    • 集群中运行了那些容器化应用程序,以及在哪个节点上运行。
    • 集群中应用程序可用的资源,如:网络、存储等。
    • 应用程序相关的策略定义,如:重启策略、升级策略和容错策略等。
    • 其他 Kubernetes 管理应用程序时所需要的信息。
  • 每一个 Kubernetes 对象都包含了两个重要字段:
    • spec:需要由我们来提供,描述了我们对该对象所期望的 目标状态
    • status:只能由 Kubernetes 系统来修改,描述了该对象在 Kubernetes 系统中的实际状态。
  • Kubernetes 通过对应的控制器(如:Deployment 等),不断的使得实际状态趋向于我们期望的目标状态。

  • 示例:查看 Deployment 时在系统底层运行的 yaml

  1. kubectl create deployment my-nginx --image=nginx -o yaml
  1. kubectl get deployment my-nginx -o yaml

1.gif

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. annotations:
  5. deployment.kubernetes.io/revision: "1"
  6. creationTimestamp: "2022-03-11T06:39:04Z"
  7. generation: 1
  8. labels:
  9. app: my-nginx
  10. name: my-nginx
  11. namespace: default
  12. resourceVersion: "21848"
  13. uid: 0919fb61-2543-49be-a6cc-9f4d41add783
  14. spec: # 期望的状态
  15. progressDeadlineSeconds: 600
  16. replicas: 1 # 副本数量
  17. revisionHistoryLimit: 10
  18. selector:
  19. matchLabels:
  20. app: my-nginx
  21. strategy:
  22. rollingUpdate:
  23. maxSurge: 25%
  24. maxUnavailable: 25%
  25. type: RollingUpdate
  26. template:
  27. metadata:
  28. creationTimestamp: null
  29. labels:
  30. app: my-nginx
  31. spec:
  32. containers:
  33. - image: nginx # 使用这个镜像创建容器
  34. imagePullPolicy: Always
  35. name: nginx
  36. resources: {}
  37. terminationMessagePath: /dev/termination-log
  38. terminationMessagePolicy: File
  39. dnsPolicy: ClusterFirst
  40. restartPolicy: Always
  41. schedulerName: default-scheduler
  42. securityContext: {}
  43. terminationGracePeriodSeconds: 30
  44. status: # 当前状态
  45. conditions:
  46. - lastTransitionTime: "2022-03-11T06:39:04Z"
  47. lastUpdateTime: "2022-03-11T06:39:04Z"
  48. message: Deployment does not have minimum availability.
  49. reason: MinimumReplicasUnavailable
  50. status: "False"
  51. type: Available
  52. - lastTransitionTime: "2022-03-11T06:39:04Z"
  53. lastUpdateTime: "2022-03-11T06:39:04Z"
  54. message: ReplicaSet "my-nginx-6b74b79f57" is progressing.
  55. reason: ReplicaSetUpdated
  56. status: "True"
  57. type: Progressing
  58. observedGeneration: 1
  59. replicas: 1
  60. unavailableReplicas: 1 # 当前集群不可用
  61. updatedReplicas: 1
  • 【问】:Kubernetes 是如何保证最终一致的?
  • 【答】:
    • etcd 保存的创建资源期望的状态以及最终这个资源的状态,这两种状态需要最终一致,即:spec 和 status 要最终一致。
    • 当输入 kubectl create deployment my-nginx --image=nginx 命令的时候,api-server 保存到 etcd ,controller-manager 会解析数据,知道集群中需要 my-nginx ,保存到 etcd 中。
    • kubelet 在底层不停的死循环使得 spec 状态和 status 最终一致,如果 spec.replicas != status.replicas ,就启动 Pod。
  1. while(true){
  2. if(status.replicas != spec.replicas){
  3. kubelet.startPod();
  4. }
  5. }

1.2 描述 Kubernetes 对象

  • 当我们在 Kubernetes 集群中床架哪一个对象的时候,我们必须提供:
    • 该对象的 spec 字段,通过该字段描述我们期望的目标状态
    • 该对象的一些基本信息,如:名字等。
  • 可以使用 kubectl 命令行创建对象,也可以使用 yaml 格式的文件进行创建。
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: nginx-deployment
  5. namespace: default
  6. labels:
  7. app: nginx
  8. spec:
  9. selector:
  10. matchLabels:
  11. app: nginx
  12. replicas: 3
  13. template:
  14. metadata:
  15. labels:
  16. app: nginx
  17. spec:
  18. containers:
  19. - name: nginx
  20. image: nginx
  21. ports:
  22. - containerPort: 80
  • 使用 kubectl apply 命令进行部署:
  1. kubectl apply -f deployment.yaml
  • 使用 kubectl delete 命令进行部署:
  1. kubectl delete -f deployment.yaml

1.3 Kubernetes 对象的 yaml 格式

2.png

  • 在上述的 yaml 文件中,如下的字段是必须填写的:
    • apiVersion:用来创建对象时所需要的 Kubernetes API 的版本,可以通过 kubectl api-resources 查询。
    • kind:创建对象的类型,可以通过 kubectl api-resources 查询。
    • metadata:用来唯一确定该对象的元数据,包括 name 、namespace 等,如果 namespace 为空,则默认值为 default 。
    • spec:翻译为 规格 ,表示我们对该对象的期望状态。

status 不需要编写,那是 Kubernetes 实际运行过程中将变化的记录保存在此字段中。

  • 不同类型的 Kubernetes ,其 spec 对象的格式不同(含有不同的内嵌字段),通过 API 手册可以查看 Kubernetes 对象的字段和描述。
  • 当然,我们以后也可以通过此地址来参照。

1.4 实际中如何创建 Kubernetes 对象的 yaml

  • ① 如果 Kubernetes 集群中已经存在了要创建的对象,那么可以使用 kubectl get 直接输出 yaml ,然后去除 status 即可:
  1. kubectl get pod xxx -o yaml > demo.yaml

3.gif

  • ② 如果 Kubernetes 集群中不存在了要创建的对象,那么可以使用类似 kubectl run xxx --dry-run=client 输出 yaml :
  1. # --dry-run=client 表示客户端干跑
  2. kubectl run nginx-pod --image=nginx --dry-run=client -o yaml > demo.yaml

4.gif

1.5 对象名称

1.5.1 概述

  • Kubernetes REST API 中,所有的对象都是通过 nameUID 唯一性的确定。
  • 可以通过 namespace + name 唯一性的确定一个 RESTful 对象,如:
  1. /api/v1/namespaces/{namespace}/pods/{name}

1.5.2 Name

  • 在同一名称空间下,同一个类型的对象,可以通过 name 来确定唯一性。如果删除该对象之后,可以再重新创建一个同名对象。
  • 根据命名规则,Kubernetes 对象的名称应该是:

    • 最长不超过 253 个字符。
    • 必须由小写字母、数字、减号 - 、小数点 . 组成。
    • 某些资源类型有更具体的要求。
  • 示例:下面的配置文件定义了一个 name 为 nginx-demo 的 Pod,该 Pod 包含一个 name 为 nginx 的 容器

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: nginx-demo ##pod的名字
  5. spec: containers:
  6. - name: nginx ##容器的名字
  7. image: nginx:1.7.9
  8. ports:
  9. - containerPort: 80

1.5.3 UID

  • UID 是由 Kubernetes 系统生成的,唯一标识某个 Kubernetes 对象的字符串。
  • Kubernetes集群中,每创建一个对象,都有一个唯一的 UID 。用于区分多次创建的同名对象(如前面所述,按照名字删除对象后,重新再创建同名对象时,两次创建的对象 name 相同,但是 UID 不同。)

5.gif

1.6 名称空间(命名空间)

1.6.1 概述

  • 在 Kubernetes 中名称空间是用来对象资源进行隔离的。
  • 默认情况下,Kubernetes 会初始化四个名称空间:
  1. kubectl get ns|namespace

6.png

  • default:所有没有指定 namespace 的对象都会被分配到此名称空间中。
  • kube-node-lease:Kubernetes 集群节点之间的心跳维护,V 1.13 开始引入。
  • kube-system:Kubernetes 系统创建的对象放在此名称空间中。
  • kube-public:此名称空间是 Kubernetes 集群安装时自动创建的,并且所有的用户都可以访问(包括未认证的用户),主要是为集群预留的,如:在某些情况中,某些 Kubernetes 对象应用应该能被所有集群用户访问到。

1.6.2 名称空间在实际开发中如何划分?

  • ① 基于环境隔离,如:dev(开发)、test(测试)、prod(生产)等。
  • ② 基于产品线隔离,如:前端、后端、中间件、大数据、Android、iOS、小程序等。
  • ③ 基于团队隔离,如:企业发展事业部、技术工程事业部、云平台事业部等。

1.6.3 名称空间的特点

  • 名称空间资源隔离、网络不隔离,如:配置文件不可以跨名称空间访问,但是网络访问可以跨名称空间访问。
  • 默认情况下,安装 Kubernetes 集群的时候,会初始化一个 default 名称空间,用来承载那些没有指定名称空间的 Pod 、Service 、Deployment 等对象。

1.6.4 名称空间的命名规则

  • ① 不能带小数点(.)。
  • ② 不能带下划线(_)。
  • ③ 使用数字、小写字母或减号(-)组成的字符串。

1.6.5 名称空间的操作

  • 示例:创建和删除名称空间(yaml )
  1. vim k8s-namespace.yaml
  1. apiVersion: v1
  2. kind: Namespace
  3. metadata:
  4. name: demo # 名称空间的名字
  5. spec: {}
  6. status: {}
  1. # 创建名称空间
  2. kubectl apply -f k8s-namespace.yaml
  1. kubectl delete -f k8s-namespace.yaml

7.gif

  • 示例:创建和删除名称空间(命令行 )
  1. # 创建名称空间
  2. kubectl create ns demo
  1. kubectl delete ns demo

8.gif

  • 示例:创建 Pod 的同时,指定自定义的名称空间(yaml)
  1. vim k8s-pod.yaml
  1. apiVersion: v1
  2. kind: Namespace
  3. metadata:
  4. name: demo # 名称空间的名字
  5. spec: {} # 默认为空,其实可以不写
  6. status: {} # 默认为空,其实可以不写
  7. # 以上是 namespace
  8. ---
  9. apiVersion: v1
  10. kind: Pod
  11. metadata:
  12. name: nginx-pod
  13. namespace: demo # 指定自定义的名称空间,如果不写,默认为 default
  14. labels:
  15. app: nginx
  16. spec:
  17. containers:
  18. - name: nginx
  19. image: nginx
  20. resources: # 后面会讲
  21. limits:
  22. cpu: 200m
  23. memory: 500Mi
  24. requests:
  25. cpu: 100m
  26. memory: 200Mi
  27. ports:
  28. - containerPort: 80
  29. name: http
  30. volumeMounts:
  31. - name: localtime
  32. mountPath: /etc/localtime
  33. volumes:
  34. - name: localtime
  35. hostPath:
  36. path: /usr/share/zoneinfo/Asia/Shanghai
  37. restartPolicy: Always
  38. # 以上的 Pod
  1. kubectl apply -f k8s-pod.yaml

9.gif

1.6.6 重点(后面讲)

  • 当我们创建一个 Service 的时候,Kubernetes 会创建一个相应的 DNS 条目
  • 该条目的形式是<service-name>.<namespace-name>.svc.cluster.local,这意味着如果容器中只使用<服务名称>,它将被解析到本地名称空间的服务器。这对于跨多个名字空间(如开发、测试和生产) 使用相同的配置非常有用。如果你希望跨名字空间访问,则需要使用完全限定域名(FQDN)。

1.6.7 注意事项

  • 大多数的 Kubernetes 资源(如:Pod、Service、副本控制器等)都位于某些名称空间中,但是名称空间本身并不在名称空间中,而且底层资源(如:node 和持久化卷)不属于任何命名空间。
  • 查看在名称空间中的资源:
  1. kubectl api-resources --namespaced=true
  • 查看不在名称空间中的资源:
  1. kubectl api-resources --namespaced=false

1.7 标签和选择器

1.7.1 概述

  • 标签(Label)是附件在 Kubernetes 对象上的一组键值对,其意图是按照对用户有意义的方式来标识 Kubernetes 镀锡,同时,又不对 Kubernetes 的核心逻辑产生影响。标签可以用来组织和选择一组 Kubernetes 对象。我们可以在创建 Kubernetes 对象的时候为其添加标签,也可以在创建以后为其添加标签。每个 Kubernetes 对象可以有多个标签,同一个对象的标签的 key 必须是唯一的,如:
  1. metadata:
  2. labels:
  3. key1: value1
  4. key2: value2
  • 使用标签(Label)可以高效的查询和监听 Kubernetes 镀锡,在 Kubernetes 界面工具(如:Kubernetes DashBoard)和 kubectl 中,标签使用的非常普遍。而那些非标识性的信息应该记录在 注解(Annotation) 中。

1.7.2 为什么要使用标签?

  • 使用标签,用户可以按照自己期望的形式组织 Kubernetes 对象之间的结构,而无需对 Kubernetes 有任何修改。
  • 应用程序的部署或者批处理程序的部署通常是多维度的(如:多个高可用分区、多个程序版本、多个微服务分层)。管理这些对象的时候,很多时候要针对某一个维护的条件做整体操作,如:将某个版本的程序整体删除。这种情况下,如果用户能够事先规划好标签的使用,再通过标签进行选择,就非常的便捷。
  • 标签的例子有:
    • release: stablerelease: canary
    • environment: devenvironment: qaenvironment: production
    • tier: frontendtier: backendtier: cache
    • partition: customerApartition: customerB
    • track: dailytrack: weekly
  • 上面只是一些使用比较普遍的标签,我们也可以根据自己的情况建立合适的标签。

1.7.3 标签的语法

  • 标签是一组键值对(key/value),标签的 key 有两个部分:可选的前缀和标签名,通过 / 分隔。
  • 标签前缀:
    • 标签前缀部分是可选的。
    • 如果指定,必须是一个 DNS 的子域名,如:k8s.eip.work 。
    • 不能多余 253 个字符。
    • 使用 / 和标签名分隔。
  • 标签名:

    • 标签名部分是必须的。
    • 不能多余 63 个字符。
    • 必须由字母、数字开始和结尾。
    • 可以包含字母、数字、减号(-)、下划线(_)、小数点(.)。

      如果省略标签前缀,则标签的 key 就被认为是专属于用户的。Kubernetes 的系统组件(如:kube-scheduler、kube-controller-manager、kube-apiserver、kubectl 或其他第三方组件)向可以的 Kubernetes 对象添加标签的时候,必须指定一个前缀。kubernetes.io/k8s.io/ 这两个前缀是 Kubernetes 核心组件预留的。

  • 标签的 value :

    • 不能多于 63 个字符。
    • 可以为空字符串。
    • 如果不为空,则必须由字母、数字开始和结尾。
    • 如果不为空,可以包含字母、数字、减号(-)、下划线(_)、小数点(.)。
  • 示例:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: nginx-pod
  5. labels: # 标签
  6. app: nginx
  7. environment: prod
  8. spec:
  9. containers:
  10. - name: nginx
  11. image: nginx

1.7.4 标签选择器

  • 通常来讲,会有多个 Kubernetes 对象包含相同的标签。通过使用标签选择器(label selector),用户/客户端可以选择一组对象。标签选择器是 Kubernetes 中最主要的分类和筛选手段。
  • Kubernetes 的 api-server 支持两种形式的标签选择器,equality-based 基于等式的set-based 基于集合的 。标签选择器可以包含多个条件,并使用逗号进行分隔,此时只要满足所有条件的 Kubernetes对象才会被选中。
  • 基于等式的标签选择器,可以使用三种操作符 ===!=。前两个操作符含义是一样的,都代表相等;后一个操作符代表不相等。
  1. # 选择了标签名为 `environment` 且 标签值为 `production` 的Kubernetes对象
  2. kubectl get pods -l environment=production,tier=frontend
  1. # 选择了标签名为 `tier` 且标签值不等于 `frontend` 的对象,以及不包含标签 `tier` 的对象
  2. kubectl get pods -l tier != frontend
  1. # 选择所有包含 `partition` 标签的对象
  2. kubectl get pods -l partition
  1. # 选择所有不包含 `partition` 标签的对象
  2. kubectl get pods -l !partition
  • 基于集合标签选择器,可以根据标签名的一组值进行筛选。支持的操作符有三种:innotinexists
  1. # 选择所有的包含 `environment` 标签且值为 `production` 或 `qa` 的对象
  2. kubectl get pods -l environment in (production, qa)
  1. # 选择所有的 `tier` 标签不为 `frontend` 和 `backend`的对象,或不含 `tier` 标签的对象
  2. kubectl get pods -l tier notin (frontend, backend)
  1. # 选择包含 `partition` 标签(不检查标签值)且 `environment` 不是 `qa` 的对象
  2. kubectl get pods -l partition,environment notin (qa)
  • 示例:Job、Deployment、ReplicaSet 和 DaemonSet 同时支持基于等式的选择方式和基于集合的选择方式。
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: nginx
  5. namespace: default
  6. labels:
  7. app: nginx
  8. spec:
  9. selector:
  10. matchLabels: # matchLabels 是一个 {key,value} 组成的 map。map 中的一个 {key,value} 条目相当于 matchExpressions 中的一个元素,其 key 为 map 的 key,operator 为 In, values 数组则只包含 value 一个元素。matchExpression 等价于基于集合的选择方式,支持的 operator 有 In、NotIn、Exists 和 DoesNotExist。当 operator 为 In 或 NotIn 时,values 数组不能为空。所有的选择条件都以 AND 的形式合并计算,即所有的条件都满足才可以算是匹配
  11. app: nginx
  12. matchExpressions:
  13. - {key: tier, operator: In, values: [cache]}
  14. - {key: environment, operator: NotIn, values: [dev]}
  15. replicas: 1
  16. template:
  17. metadata:
  18. labels:
  19. app: nginx
  20. spec:
  21. containers:
  22. - name: nginx
  23. image: nginx:latest

1.7.5 标签的操作

  • 示例:添加标签
  1. kubectl label pod nginx-pod hello=world
  • 示例:更新标签
  1. kubectl label pod nginx-pod hello=java
  • 示例:删除标签
  1. kubectl label pod nginx-pod hello-

1.8 注解 annotations

  • 注解(annotation) 可以用来向 Kubernetes 对象的 meta.annotations 字段添加任意的信息。Kubernetes 的客户端或者自动化工具可以存取这些信息以实现自定义的逻辑。
  1. metadata:
  2. annotations:
  3. key1: value1
  4. key2: value2

1.9 给 VScode 安装插件

  • 推荐在 Vscode 中安装如下的插件,可以加快编写 Kubernetes 的 yaml 的速度:

10.png

11.png

1.10 重新认识 kubectl 和 kubelet

  • 核心文件夹:/etc/kubernetes
  • kubelet 额外参数配置: /etc/sysconfig/kubelet
  • kubelet配置位置: /var/lib/kubelet/config.yaml

第二章:万物基础 — 容器

2.1 镜像

2.1.1 概述

  • 平时,我们使用 Docker 的镜像非常之简单,类似于下面的命令:
  1. docker pull nginx:latest
  • 其实,完整的写法应该是这样:
  1. docker pull docker.io/library/nginx:latest
  • 如果我们使用自己搭建过 Docker 的私有镜像仓库,可以发现会出现如下的命令:
  1. docker push 192.168.65.100:5000/xudaxian/ubuntu:1.0
  • 说明:
    • 192.168.65.100:镜像仓库的地址。
    • 5000:镜像仓库的端口。
    • xudaxian:镜像仓库的名称。
    • ubuntu:镜像的名称。
    • 1.0:镜像的版本,如果不写,默认就是 latest 。
  • 当然,如果拉取的是 hub.docker.com 中的镜像,那么镜像仓库地址以及端口都可以省略。

2.1.2 Kubernetes 中的镜像

  • 在 Kubernetes 的 Pod 定义容器的时候,必须指定容器所使用的镜像,容器中的 image 字段支持的语法和 docker 命令是一样的,包括私有镜像仓库和标签,如:
  1. # 192.168.65.100:5000/xudaxian/ubuntu:1.0
  2. my-registry.example.com:5000/example/web-example:v1.0

注意:在生产环境中,建议锁定镜像的版本。

  • 示例:
  1. apiVersion: v1
  2. kind: Namespace
  3. metadata:
  4. name: demo
  5. spec: {}
  6. status: {}
  7. # 以上是 namespace
  8. ---
  9. apiVersion: v1
  10. kind: Pod
  11. metadata:
  12. name: nginx-pod
  13. namespace: demo
  14. labels:
  15. app: nginx
  16. spec:
  17. containers:
  18. - name: nginx
  19. image: nginx:1.20.2 # Docker 的镜像名称,和 Docker 命令一样,my-registry.example.com:5000/example/web-example:v1.0,实际开发中,建议锁定镜像的版本。
  20. ports:
  21. - containerPort: 80
  22. # 以上的 Pod
  • Kubernetes 中的镜像拉取策略:

    • IfNotPresent(默认) :只有当镜像在本地不存在时才会拉取。
    • Always :每当 kubelet 启动一个容器时,kubelet 会查询容器的镜像仓库, 将名称解析为一个镜像摘要。 如果 kubelet 有一个容器镜像,并且对应的摘要已在本地缓存,kubelet 就会使用其缓存的镜像; 否则,kubelet 就会使用解析后的摘要拉取镜像,并使用该镜像来启动容器。
    • Never :Kubelet 不会尝试获取镜像。如果镜像已经以某种方式存在本地, kubelet 会尝试启动容器;否则,会启动失败。
  • 示例:

  1. apiVersion: v1
  2. kind: Namespace
  3. metadata:
  4. name: demo
  5. spec: {}
  6. status: {}
  7. # 以上是 namespace
  8. ---
  9. apiVersion: v1
  10. kind: Pod
  11. metadata:
  12. name: nginx-pod
  13. namespace: demo
  14. labels:
  15. app: nginx
  16. spec:
  17. containers:
  18. - name: nginx
  19. image: nginx:1.20.2 # Docker 的镜像名称,和 Docker 命令一样,my-registry.example.com:5000/example/web-example:v1.0,实际开发中,建议锁定镜像的版本。
  20. imagePullPolicy: Always # 镜像拉取策略:IfNotPresent(默认)、Always、Never
  21. ports:
  22. - containerPort: 80
  23. # 以上的 Pod

2.1.3 下载私有仓库的镜像

  • 我们在使用阿里云容器镜像的私有仓库的使用,阿里云要求我们进行登录,如果是 docker 拉取镜像,那么只需要 docker login 之类的就可以了;但是,如果使用 Kubernetes 该怎么办?
  • ① 创建 secret :
  1. # -n demo :表示该密钥将只在指定的名称空间 demo 中生效
  2. # docker-registry aliyun :指定 Docker 镜像仓库的名称
  3. # --docker-server:Docker 镜像仓库的地址
  4. # --docker-username:Docker 镜像仓库的用户名
  5. # --docker-password:Docker 镜像仓库的密码
  6. kubectl create secret -n demo docker-registry aliyun \
  7. --docker-server=registry.cn-shanghai.aliyuncs.com \
  8. --docker-username=xudaxian \
  9. --docker-password=123456
  • ② 在 yaml 中拉取镜像的时候设置镜像拉取的密钥(secret):
  1. apiVersion: v1
  2. kind: Namespace
  3. metadata:
  4. name: demo
  5. spec: {}
  6. status: {}
  7. # 以上是 namespace
  8. ---
  9. apiVersion: v1
  10. kind: Pod
  11. metadata:
  12. name: demo-pod
  13. namespace: demo
  14. labels:
  15. app: nginx
  16. spec:
  17. containers:
  18. imagePullSecrets: # Pull镜像时使用的 secret 名称,以 key:secretkey 格式指定
  19. - name: aliyun
  20. - name: nginx
  21. image: nginx:1.20.2 # Docker 的镜像名称,和 Docker 命令一样,my-registry.example.com:5000/example/web-example:v1.0,实际开发中,建议锁定镜像的版本。
  22. imagePullPolicy: Always # 镜像拉取策略:IfNotPresent(默认)、Always、Never
  23. - name: arcgis
  24. image: registry.cn-shanghai.aliyuncs.com/xudaxian/arcgis/v1.0
  25. imagePullPolicy: Always

注意:这个肯定运行不了,需要将 secret 的用户名和密码设置为自己的,而且在拉取阿里云私有镜像的时候设置为自己的镜像。

2.2 环境变量

  • 使用 env 用来给 Pod 中的容器设置环境变量,相当于 docker run -e xxx=xxx 中的 -e 参数。

  • 示例:

  1. vim k8s-mysql.yaml
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: mysql-pod
  5. namespace: default
  6. labels:
  7. app: mysql-pod
  8. spec:
  9. containers:
  10. - name: mysql-pod
  11. image: mysql:5.7
  12. env: # 环境变量 相当于 docker run -e xxx = xxx
  13. - name: MYSQL_ROOT_PASSWORD # root 的密码
  14. value: "123456"
  15. - name: MYSQL_DATABASE # mysql 的 数据库
  16. value: ssm
  17. restartPolicy: Always
  1. kubectl apply -f k8s-mysql.yaml

12.gif

2.3 启动命令

  • Docker 的镜像拥有存储镜像信息的相关元数据,如果不设置生命周期命令和参数,容器运行时会运行镜像制作时提供的默认的命令和参数,Docker 原生定义这两个字段为 ENTRYPOINTCMD
  • 如果在创建工作负载时填写了容器的运行命令和参数,将会覆盖镜像构建时的默认命令 EntrypointCMD,规则如下: | 镜像 Entrypoint | 镜像CMD | 容器 command | 容器 args | 最终执行 | | —- | —- | —- | —- | —- | | [touch] | [/root/test] | 未设置 | 未设置 | [touch /root/test] | | [touch] | [/root/test] | [mkdir] | 未设置 | [mkdir] | | [touch] | [/root/test] | 未设置 | [/opt/test] | [touch /opt/test] | | [touch] | [/root/test] | [mkdir] | [/opt/test] | [mkdir /opt/test] |
  • 换言之,如果在 Kubernetes 的 yaml 中定义了 comand 和 args ,那么就会覆盖 Dockerfile 中的 ENTRPOINT 和 CMD 。

  • 示例:启动 MySQL

  1. vim k8s-mysql.yaml
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: mysql-pod
  5. namespace: default
  6. labels:
  7. app: mysql-pod
  8. spec:
  9. containers:
  10. - name: mysql-pod
  11. image: mysql:5.7
  12. env:
  13. - name: MYSQL_ROOT_PASSWORD
  14. value: "123456"
  15. - name: MYSQL_DATABASE
  16. value: ssm
  17. args:
  18. - "--lower_case_table_names=1"
  19. - "--character-set-server=utf8mb4"
  20. - "--collation-server=utf8mb4_general_ci"
  21. - "--default-authentication-plugin=mysql_native_password"
  22. ports:
  23. - containerPort: 3306
  24. restartPolicy: Always
  1. kubectl apply -f k8s-mysql.yaml

13.gif

2.4 资源限额

  • 器中的程序要运行,肯定会占用一定的资源,比如 CPU 和内存等,如果不对某个容器的资源做限制,那么它就可能吃掉大量的资源,导致其他的容器无法运行。
  • 针对上面的情况,Kubernetes 提供了对内存和 CPU 的资源进行配额的机制,这种机制主要通过 resources 选项实现,它有两个子选项:
    • limits:用于限制运行的容器的最大占用资源,当容器占用资源超过 limits 时会被终止,并进行重启。
    • requests:用于设置容器需要的最小资源,如果环境资源不够,容器将无法启动。
      • cpu:core 数,可以为整数或小数,1 == 1000m。
      • memory:内存大小,可以使用 Gi、 Mi、G、M 等形式。
  • 示例:
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: nginx-pod
  5. labels:
  6. app: nginx
  7. spec:
  8. containers:
  9. - name: nginx
  10. image: nginx:1.20.2
  11. resources: # 资源限制
  12. limits:
  13. cpu: 2
  14. memory: 1500M
  15. requests:
  16. cpu: 1
  17. memory: 1024M
  18. ports:
  19. - containerPort: 80
  20. restartPolicy: Always