Setup

Instructions for setting up a Kubernetes cluster.

Edit This Page

从零开始搭建自定义集群

本指南适用于想要搭建一个定制化 Kubernetes 集群的人员。如果您在 列表 中找到现有的入门指南可以满足您的需求,那么建议使用它们,因为可从他人的经验中获益。但是,如果您使用特定的 IaaS,网络,配置管理或操作系统,同时又不符合这些指南的要求,那么本指南会为您提供所需的步骤大纲。请注意,比起其他预定义的指南,研习本指南需做出相当多的努力。

本指南对那些想要从更高层次了解现有集群安装脚本执行步骤的人员也很有用。

设计和准备

学习

  1. 您应该已经熟悉使用 Kubernetes 集群。建议按照如下入门指南启动一个临时的集群。首先帮您熟悉 CLI(kubectl)和概念(podsservices等)。
  2. 您的工作站应该已经存在 ‘kubectl’。这是完成其他入门指南后的一个附加安装。如果没有,请遵循 说明

Cloud Provider

Kubernetes 的 Cloud Provider 是一个模块,它提供一个管理 TCP 负载均衡,节点(实例)和网络路由的接口。此接口定义在 pkg/cloudprovider/cloud.go。未实现 Cloud Provider 也可以建立自定义集群(例如使用裸机),并不是所有的接口功能都必须实现,这取决于如何在各组件上设置标识。

节点

网络

网络连接

Kubernetes 有一个独特的 网络模型

Kubernetes 为每个 pod 分配一个 IP 地址。创建集群时,需要为 Kubernetes 分配一段 IP 以用作 pod 的 IP。最简单的方法是为集群中的每个节点分配不同的 IP 段。 pod 中的进程可以访问其他 pod 的 IP 并与之通信。这种连接可以通过两种方式实现:

选择哪种方式取决于您的环境和需求。有多种方法来实现上述的某种选项:

需要为 Pod IP 选择一个地址范围。请注意,Pod IP 尚不支持 IPv6。

Kubernetes 也为每个 service 分配一个 IP。但是,Service IP 无须路由。在流量离开节点前,kube-proxy 负责将 Service IP 转换为 Pod IP。您需要利用 SERVICE_CLUSTER_IP_RANGE 为 service 分配一段 IP。例如,设置 SERVICE_CLUSTER_IP_RANGE="10.0.0.0/16" 以允许激活 65534 个不同的服务。请注意,您可以增大此范围,但在不中断使用它的 service 和 pod 时,您不能移动该范围(指增大下限或减小上限)。

此外,您需要为主节点选择一个静态 IP。

网络策略

Kubernetes 可以在 Pods 之间使用 网络策略 定义细粒度的网络策略。

并非所有网络提供商都支持 Kubernetes NetworkPolicy API,参阅 使用网络策略 获取更多内容。

集群命名

您应该为集群选择一个名称。为每个集群选择一个简短的名称并在以后的集群使用中将其作为唯一命名。以下几种方式中都会用到集群名称:

软件的二进制文件

您需要以下二进制文件:

下载并解压 Kubernetes 二进制文件

Kubernetes 发行版包括所有的 Kubernetes 二进制文件以及受支持的 etcd 发行版。 您可以使用 Kubernetes 的发行版(推荐)或按照 开发人员文档 中的说明构建您的 Kubernetes 二进制文件。本指南仅涉及使用 Kubernetes 发行版。

下载并解压 最新的发行版。服务器二进制 tar 包不再包含在 Kubernetes 的最终 tar 包中,因此您需要找到并运行 ./kubernetes/cluster/get-kube-binaries.sh 来下载客户端和服务器的二进制文件。 然后找到 ./kubernetes/server/kubernetes-server-linux-amd64.tar.gz 并解压缩。接着在被解压开的目录 ./kubernetes/server/bin 中找到所有必要的二进制文件。

选择镜像

您将在容器之外运行 docker,kubelet 和 kube-proxy,与运行系统守护进程的方式相同,这些程序需要单独的二进制文件。对于 etcd,kube-apiserver,kube-controller-manager 和 kube-scheduler,我们建议您将其作为容器运行,因此需要构建相应的镜像。

获取 Kubernetes 镜像的几种方式:

使用 etcd:

我们建议您使用 Kubernetes 发行版中提供的 etcd。Kubernetes 程序已经使用此版本的 etcd 进行了广泛的测试,而不是与任何其他版本的 etcd。推荐的版本号也可以在 kubernetes/cluster/images/etcd/Makefile 中作为 TAG 的值被找到。

该文档的剩余部分假定镜像标签已被选定并存储在相应的环境变量中。例子(替换最新的标签和适当的仓库源):

安全模型

两种主要的安全方式:

如果遵循 HTTPS 方法,则需要准备证书和凭证。

准备证书

您需要准备几种证书:

除非您打算用一个真正的 CA 生成证书,否则您需要生成一个根证书,并使用它来签署主节点,kubelet 和 kubectl 证书。在 认证文档 中描述了如何做到这一点。

最终您会得到以下文件(稍后将用到这些变量)

准备凭证

管理员用户(和任何用户)需要:

您的令牌和密码需要存储在文件中才能被 apiserver 读取。本指南使用 /var/lib/kube-apiserver/known_tokens.csv。此文件的格式在 身份验证文档 中有描述。

为了向客户端分发凭证,Kubernetes 约定将凭证放入 kubeconfig 文件 中。

可以创建管理员的 kubeconfig 文件,如下所示:

接下来,为 kubelet 和 kube-proxy 创建一个 kubeconfig 文件。创建多少不同文件有几种选择:

  1. 使用与管理员相同的凭证 - 这是最简单的设置。
  2. 所有 kubelet 用一套令牌和 kubeconfig 文件,kube-proxy 用一套,管理端用一套。 - 这是如今在 GCE 上的方式
  3. 每个 kubelet 使用不同的凭证 - 我们正在改进,但所有的细节还没有准备好。

您可以通过拷贝 $HOME/.kube/config、参考 cluster/gce/configure-vm.sh 中的代码或者使用下面的模板来创建这些文件:

apiVersion: v1
kind: Config
users:
- name: kubelet
  user:
    token: ${KUBELET_TOKEN}
clusters:
- name: local
  cluster:
    certificate-authority: /srv/kubernetes/ca.crt
contexts:
- context:
    cluster: local
    user: kubelet
  name: service-account-context
current-context: service-account-context

将 kubeconfig 文件放在每个节点上。以后本指南的例子假设在 /var/lib/kube-proxy/kubeconfig/var/lib/kube-proxy/kubeconfig 中有 kubeconfig。

在节点上配置和安装基础软件

本节讨论如何将机器配置为 Kubernetes 节点。

您应该在每个节点上运行三个守护进程:

您还需要在安装操作系统后进行各种其他配置。

提示:比较可行的方法是先使用现有的入门指南来设置集群。在集群运行后,您可以从该集群复制 init.d 脚本或 systemd 单元文件,然后修改它们以便在您的自定义集群上使用。

Docker

所需 Docker 的最低版本随 kubelet 版本的更改而变化。推荐使用最新的稳定版。如果版本太旧,Kubelet 将抛出警告并拒绝启动 pod,请尝试更换合适的 Docker 版本。

如果您已经安装过 Docker,但是该节点并没有配置过 Kubernetes,那么节点上可能存在 Docker 创建的网桥和 iptables 规则。您可能需要像下面这样删除这些内容,然后再为 Kubernetes 配置 Docker。

iptables -t nat -F
ip link set docker0 down
ip link delete docker0

配置 docker 的方式取决于您是否为网络选择了可路由的虚拟 IP 或 overlay 网络方式。Docker 的建议选项:

如果想增加 docker 的文件打开数量,设置:

此配置方式取决于您节点上的操作系统。例如在 GCE 上,基于 Debian 的发行版使用 /etc/default/docker

通过 Docker 文档中给出的示例,确保在继续安装其余部分之前,您系统上的 docker 工作正常。

rkt

rkt 是 Docker 外的另一种选择,您只需要安装 Docker 或 rkt 之一。其最低版本要求 v0.5.6

您的节点需要 systemd 来运行 rkt。匹配 rkt v0.5.6 的最小版本是 systemd 215

对 rkt 的网络支持还需要 rkt 元数据服务。您可以使用命令启动 rkt 元数据服务 sudo systemd-run rkt metadata-service

然后,您需要将该参数配置到 kubelet:

kubelet

所有节点都应该运行 kubelet。参阅 软件的二进制文件

要考虑的参数:

kube-proxy

所有节点都应该运行 kube-proxy。(并不严格要求在“主”节点上运行 kube-proxy,但保持一致更简单。) 下载使用 kube-proxy 的方法和 kubelet 一样。

要考虑的参数:

网络

每个节点需要分配自己的 CIDR 范围,用于 pod 网络。称为 NODE_X_POD_CIDR

需要在每个节点上创建一个名为 cbr0 的网桥。在 网络文档 中进一步说明了该网桥。网桥本身需要从 $NODE_X_POD_CIDR 获取一个地址,按惯例是第一个 IP。称为 NODE_X_BRIDGE_ADDR。例如,如果 NODE_X_POD_CIDR10.0.0.0/16,则NODE_X_BRIDGE_ADDR10.0.0.1/16。 注意:由于以后使用这种方式,因此会保留后缀 /16

如果您已经关闭 Docker 的 IP 伪装,以允许pod相互通信,那么您可能需要为集群网络之外的目标 IP 进行伪装。例如:

iptables -t nat -A POSTROUTING ! -d ${CLUSTER_SUBNET} -m addrtype ! --dst-type LOCAL -j MASQUERADE

对于集群外部的流量,这将重写从 PodIP 到节点 IP 的源地址,并且内核 连接跟踪 将确保目的地为节点地址的流量仍可抵达 pod。

注意:以上描述适用于特定的环境。其他环境根本不需要伪装。如 GCE,不允许 Pod IP 向外网发送流量,但在您的 GCE 项目内部之间没有问题。

其他

使用配置管理

之前的步骤都涉及用于设置服务器的“常规”系统管理技术。您可能希望使用配置管理系统来自动执行节点配置过程。在各种入门指南中有 Ansible,Juju 和 CoreOS Cloud Config 的示例 Saltstack

引导集群启动

虽然基础节点服务(kubelet, kube-proxy, docker)还是由传统的系统管理/自动化方法启动和管理,但是 Kubernetes 中其余的 master 组件都由 Kubernetes 配置和管理:

etcd

您需要运行一个或多个 etcd 实例。

有关影响集群可用性因素的更多讨论,请参阅 cluster-troubleshooting

运行一个 etcd 实例:

  1. 复制 cluster/saltbase/salt/etcd/etcd.manifest
  2. 按需要进行修改
  3. 通过将其放入 kubelet 清单目录来启动 pod。

Apiserver, Controller Manager, and Scheduler

Apiserver,Controller Manager和 Scheduler 将分别以 pod 形式在主节点上运行。。

对于这些组件,启动它们的步骤类似:

  1. 从所提供的 pod 模板开始。
  2. 选取镜像 中的值设置到 HYPERKUBE_IMAGE
  3. 使用每个模板下面的建议,确定集群需要哪些参数。
  4. 将完成的模板放入 kubelet 清单目录中启动 pod。
  5. 验证 pod 是否启动。

Apiserver pod 模板

{
  "kind": "Pod",
  "apiVersion": "v1",
  "metadata": {
    "name": "kube-apiserver"
  },
  "spec": {
    "hostNetwork": true,
    "containers": [
      {
        "name": "kube-apiserver",
        "image": "${HYPERKUBE_IMAGE}",
        "command": [
          "/hyperkube",
          "apiserver",
          "$ARG1",
          "$ARG2",
          ...
          "$ARGN"
        ],
        "ports": [
          {
            "name": "https",
            "hostPort": 443,
            "containerPort": 443
          },
          {
            "name": "local",
            "hostPort": 8080,
            "containerPort": 8080
          }
        ],
        "volumeMounts": [
          {
            "name": "srvkube",
            "mountPath": "/srv/kubernetes",
            "readOnly": true
          },
          {
            "name": "etcssl",
            "mountPath": "/etc/ssl",
            "readOnly": true
          }
        ],
        "livenessProbe": {
          "httpGet": {
            "scheme": "HTTP",
            "host": "127.0.0.1",
            "port": 8080,
            "path": "/healthz"
          },
          "initialDelaySeconds": 15,
          "timeoutSeconds": 15
        }
      }
    ],
    "volumes": [
      {
        "name": "srvkube",
        "hostPath": {
          "path": "/srv/kubernetes"
        }
      },
      {
        "name": "etcssl",
        "hostPath": {
          "path": "/etc/ssl"
        }
      }
    ]
  }
}

以下是您可能需要设置的一些 apiserver 参数:

如果您遵循仅防火墙的安全方法,请使用以下参数:

如果您使用 HTTPS 方法,请设置:

pod 使用 hostPath 卷挂载几个节点上的文件系统目录。这样的目的是:

待办 文档化 proxy-ssh 的安装

Cloud Provider

Apiserver 支持若干 cloud providers。

一些 cloud provider 需要一个配置文件。如果是这样,您需要将配置文件放入 apiserver 镜像或通过 hostPath 挂载。

Scheduler pod 模板

完成 Scheduler pod 模板:

{
  "kind": "Pod",
  "apiVersion": "v1",
  "metadata": {
    "name": "kube-scheduler"
  },
  "spec": {
    "hostNetwork": true,
    "containers": [
      {
        "name": "kube-scheduler",
        "image": "$HYBERKUBE_IMAGE",
        "command": [
          "/hyperkube",
          "scheduler",
          "--master=127.0.0.1:8080",
          "$SCHEDULER_FLAG1",
          ...
          "$SCHEDULER_FLAGN"
        ],
        "livenessProbe": {
          "httpGet": {
            "scheme": "HTTP",
            "host": "127.0.0.1",
            "port": 10251,
            "path": "/healthz"
          },
          "initialDelaySeconds": 15,
          "timeoutSeconds": 15
        }
      }
    ]
  }
}

通常,调度程序不需要额外的标志。

或者,您也可能需要挂载 /var/log,并重定向输出到这里。

Controller Manager 模板

Controller Manager pod 模板

{
  "kind": "Pod",
  "apiVersion": "v1",
  "metadata": {
    "name": "kube-controller-manager"
  },
  "spec": {
    "hostNetwork": true,
    "containers": [
      {
        "name": "kube-controller-manager",
        "image": "$HYPERKUBE_IMAGE",
        "command": [
          "/hyperkube",
          "controller-manager",
          "$CNTRLMNGR_FLAG1",
          ...
          "$CNTRLMNGR_FLAGN"
        ],
        "volumeMounts": [
          {
            "name": "srvkube",
            "mountPath": "/srv/kubernetes",
            "readOnly": true
          },
          {
            "name": "etcssl",
            "mountPath": "/etc/ssl",
            "readOnly": true
          }
        ],
        "livenessProbe": {
          "httpGet": {
            "scheme": "HTTP",
            "host": "127.0.0.1",
            "port": 10252,
            "path": "/healthz"
          },
          "initialDelaySeconds": 15,
          "timeoutSeconds": 15
        }
      }
    ],
    "volumes": [
      {
        "name": "srvkube",
        "hostPath": {
          "path": "/srv/kubernetes"
        }
      },
      {
        "name": "etcssl",
        "hostPath": {
          "path": "/etc/ssl"
        }
      }
    ]
  }
}

使用 controller manager 时需要考虑的标志:

启动和验证 Apiserver,Scheduler 和 Controller Manager

将每个完成的 pod 模板放入 kubelet 配置目录中(kubelet 的参数 --config= 参数设置的值,通常是 /etc/kubernetes/manifests)。顺序不重要:scheduler 和 controller manager 将重试到 apiserver 的连接,直到它启动为止。

使用 psdocker ps 来验证每个进程是否已经启动。例如,验证 kubelet 是否已经启动了一个 apiserver 的容器:

$ sudo docker ps | grep apiserver:
5783290746d5        gcr.io/google_containers/kube-apiserver:e36bf367342b5a80d7467fd7611ad873            "/bin/sh -c '/usr/lo'"    10 seconds ago      Up 9 seconds                              k8s_kube-apiserver.feb145e7_kube-apiserver-kubernetes-master_default_eaebc600cf80dae59902b44225f2fc0a_225a4695

然后尝试连接到 apiserver:

$ echo $(curl -s http://localhost:8080/healthz)
ok
$ curl -s http://localhost:8080/api
{
  "versions": [
    "v1"
  ]
}

如果您为 kubelet 选择了 --register-node=true 选项,那么它们向 apiserver 自动注册。 您应该很快就可以通过运行 kubectl get nodes 命令查看所有节点。 否则,您需要手动创建节点对象。

启动集群服务

您将希望通过添加集群范围的服务来完成您的 Kubernetes 集群。这些有时被称为 addons,查阅在 管理指南 中的概述。

下面给出了设置每个集群服务的注意事项:

故障排除

运行 validate-cluster

cluster/kube-up.sh 调用 cluster/validate-cluster.sh 用于确定集群启动是否成功。

使用和输出示例:

KUBECTL_PATH=$(which kubectl) NUM_NODES=3 KUBERNETES_PROVIDER=local cluster/validate-cluster.sh
Found 3 node(s).
NAME                    STATUS    AGE     VERSION
node1.local             Ready     1h      v1.6.9+a3d1dfa6f4335
node2.local             Ready     1h      v1.6.9+a3d1dfa6f4335
node3.local             Ready     1h      v1.6.9+a3d1dfa6f4335
Validate output:
NAME                 STATUS    MESSAGE              ERROR
controller-manager   Healthy   ok
scheduler            Healthy   ok
etcd-1               Healthy   {"health": "true"}
etcd-2               Healthy   {"health": "true"}
etcd-0               Healthy   {"health": "true"}
Cluster validation succeeded

检查 pod 和 service

尝试通过其他入门指南中的 “检查集群” 部分,例如 GCE。您应该看到一些服务。还应该看到 apiserver,scheduler 和 controller-manager 的 “镜像 pod”,以及您启动的任何加载项。

试一试例子

此时,您应该能够运行一个基本的例子,例如 nginx 例子

运行一致性测试

您可能想尝试运行 一致性测试。任何失败都会给一个提示,您需要更多地关注它们。

网络

节点必须能够使用其私有 IP 通讯。从一个节点到另一个节点使用 ping 或 SSH 命令进行验证。

帮助

如果您遇到问题,请参阅 troubleshooting,联系 kubernetes 用户组,或者在 Slack 提问。

支持级别

IaaS 提供商 配置管理 系统 网络 文档 整合 支持级别
任何 任何 任何 任何 文档   社区 (@erictune)

有关所有解决方案的支持级别信息,请参阅图表 解决方案表

Analytics

Create an Issue Edit this Page