Fork me on GitHub

自建 Kubernetes 上运行容器

编写配置文件

Kubernetes 跟 Docker 等很多项目最大的不同,就在于它不推荐你使用命令行的方式直接运行容器(虽然 Kubernetes 项目也支持这种方式,比如:kubectl run),而是希望你用 YAML 文件的方式,即:把容器的定义、参数、配置,统统记录在一个 YAML 文件中,然后用这样一句指令把它运行起来:

$ kubectl create -f 我的配置文件

Yaml文件示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
  • 像这样的一个 YAML 文件,对应到 Kubernetes 中,就是一个 API Object(API 对象)。当你为这个对象的各个字段填好值并提交给 Kubernetes 之后,Kubernetes 就会负责创建出这些对象所定义的容器或者其他类型的 API 资源。
  • 这个 YAML 文件中的 Kind 字段,指定了这个 API 对象的类型(Type),是一个 Deployment。Deployment,是一个定义多副本应用(即多个副本 Pod)的对象
  • 这个 YAML 文件中,定义的 Pod 副本个数 (spec.replicas) 是:2。
  • Pod 模版(spec.template),这个模版描述了创建的 Pod 的细节。在上面的例子这个 Pod 里只有一个容器,这个容器的镜像(spec.containers.image)是 nginx:1.7.9,这个容器监听端口(containerPort)是 80。
  • 这样使用一种 API 对象(Deployment)管理另一种 API 对象(Pod)的方法,在 Kubernetes 中,叫作“控制器”模式(controller pattern)
  • 一个 Kubernetes 的 API 对象的定义,大多可以分为 Metadata 和 Spec 两个部分。前者存放的是这个对象的元数据,对所有 API 对象来说,这一部分的字段和格式基本上是一样的;而后者存放的,则是属于这个对象独有的定义,用来描述它所要表达的功能。
[root@k8s ~]# kubectl apply -f nginx-deployment.yaml --namespace=kube-system
deployment.apps/nginx-deployment created
[root@k8s ~]# kubectl get pods -l app=nginx
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-54f57cf6bf-jpgq4   0/1     Pending   0          86m
nginx-deployment-54f57cf6bf-rrmbq   0/1     Pending   0          86m

或者
[root@k8s ~]# kubectl get pods -n kube-system

解决 pending 状态:
检查:
[root@k8s ~]# kubectl -n kube-system describe pod nginx-deployment-54f57cf6bf-rg8td
……
……
Events:
  Type     Reason            Age                From               Message
  ----     ------            ----               ----               -------
  Warning  FailedScheduling  5s (x17 over 22m)  default-scheduler  0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate.

查看节点的 Taints(kubectl describe node <node_name>)
Taints:   node-role.kubernetes.io/master:NoSchedule

解决方案:

  • 在 Pod 的.yaml 文件中的 spec 部分,加入 tolerations 字段即可
  • 或者 kubectl taint nodes --all node-role.kubernetes.io/master-

在“node-role.kubernetes.io/master”这个键后面加上了一个短横线“-”,这个格式就意味着移除所有以“node-role.kubernetes.io/master”为键的 Taint。

[root@k8s ~]# kubectl taint nodes --all node-role.kubernetes.io/master-
node/instance-010oj085 untainted

再次查看状态(在命令行中,所有 key-value 格式的参数,都使用“=”而非“:”表示)

[root@k8s ~]# kubectl get pods -l app=nginx
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-54f57cf6bf-jpgq4   1/1     Running   0          148m
nginx-deployment-54f57cf6bf-rrmbq   1/1     Running   0          148m

查看 describe 的 Event 事件:

……
Events:
  Type     Reason            Age                 From                        Message
  ----     ------            ----                ----                        -------
  Warning  FailedScheduling  10m (x39 over 65m)  default-scheduler           0/1 nodes are available: 1 node(s) had taints that the pod didn't tolerate.
  Normal   Pulling           5m41s               kubelet, instance-010oj085  Pulling image "nginx:1.7.9"
  Normal   Pulled            4m37s               kubelet, instance-010oj085  Successfully pulled image "nginx:1.7.9"
  Normal   Created           4m37s               kubelet, instance-010oj085  Created container nginx
  Normal   Started           4m37s               kubelet, instance-010oj085  Started container nginx

镜像服务升级

1. 修改 YAML 文件

2. 执行命令
# 修改nginx-deployment.yaml的内容
kubectl apply -f nginx-deployment.yaml

当应用本身发生变化时,开发人员和运维人员可以依靠容器镜像来进行同步;当应用部署参数发生变化时,这些 YAML 文件就是他们相互沟通和信任的媒介。

删除 Nginx Deployment

$ kubectl delete -f nginx-deployment.yaml

总结

  • Kubernetes 里“最小”的 API 对象是 Pod。Pod 可以等价为一个应用,所以,Pod 可以由多个紧密协作的容器组成。
  • 在 Kubernetes 中,我们经常会看到它通过一种 API 对象来管理另一种 API 对象,比如 Deployment 和 Pod 之间的关系;而由于 Pod 是“最小”的对象,所以它往往都是被其他对象控制的。这种组合方式,正是 Kubernetes 进行容器编排的重要模式。
  • 像这样的 Kubernetes API 对象,往往由 Metadata 和 Spec 两部分组成,其中 Metadata 里的 Labels 字段是 Kubernetes 过滤对象的主要手段。
  • 在这些字段里面,容器想要使用的数据卷,也就是 Volume,正是 Pod 的 Spec 字段的一部分。而 Pod 里的每个容器,则需要显式的声明自己要挂载哪个 Volume。
posted @ 2020-04-04 17:22  galvinwang  阅读(335)  评论(0编辑  收藏  举报