不知道有没有人和我同样,在手动安装时由于不少缘由没有成功(主要仍是知识储备不够),被各类高可用配置和各类证书权限弄得迷迷糊糊。这个笔记是我在尝试了不少种手动安装Kubernetes集群教程中的方法失败后产生的想法,但愿可以将复杂的配置化繁为简,呈现出一个基本功能的Kubernetes程序,记录下如何以最简的方式配置各个组件,使其可以实现基本的功能。而后再逐步添加多节点、安全认证、高可用等复杂配置,经过这个过程来理解Kubernetes各类基础组件之间的关系已经配置方法。html
计划的第一步就是完成一个非安全的单 master 单 node 集群,api-server 和 kubelet 等组件都经过systemd来管理,master 上不安装kubelet 只作管理端使用。首先我尝试用比较新的 1.10.X 版k8s 安装,可是安装过程当中没有办法用非证书认证方式指定 api-server 的地址,彷佛官方在有意逐步取消对非安全方式的支持。最后仍是选择了比较旧的k8s 1.6.0 来完成安装。node
主机名 | IP地址 | 角色 | CPU/内存 |
---|---|---|---|
u16-1 | 192.168.112.148 | master(only as master) | 2核/2G |
u16-2 | 192.168.112.149 | node | 2核/2G |
从 github 的 Kubernetes 项目页面 上找到咱们须要的 V1.6.0版本,而后点击 CHANGELOG,在 Older releases 下面点击 CHANGELOG-1.6.md ,找到 v1.6.0 版本的 Server Binaries 中对应的架构的包(kubernetes-server-linux-amd64.tar.gz)下载并上传到服务器(国内上网环境可能没法正常下载)linux
k8s 1.6.0 对应的 etcd 版本为 v3.0.14,一样能够从 github 上 etcd 项目对应版本的页面找到并下载到服务器git
wget https://github.com/etcd-io/etcd/releases/download/v3.0.14/etcd-v3.0.14-linux-amd64.tar.gz
关闭 swap并在 /etc/fstab 文件中取消掉自动挂载github
sudo swapoff -a
若是系统上安装了SELinux,须要将其关闭。另外还须要在防火墙上放开下面步骤中全部须要使用的端口,或者关闭防火墙管理软件,我这里选择将ubuntu16.04默认的ufw关闭docker
sudo ufw disable
tar xf etcd-v3.0.14-linux-amd64.tar.gz #把解压后的 etcd 和 etcdctl 复制到 /usr/bin 目录下 sudo cp etcd-v3.0.14-linux-amd64/etcd{,ctl} /usr/bin/
而后设置 systemd 服务文件 /lib/systemd/system/etcd.serviceubuntu
[Unit] Description=Etcd Server After=network.target [Service] Type=notify WorkingDirectory=/var/lib/etcd/ EnvironmentFile=-/etc/etcd/etcd.conf ExecStart=/usr/bin/etcd [Install] WantedBy=multi-user.target
这里 WorkingDirectory 指定的目录须要提早建立好,这个目录将做为etcd数据保存的目录。api
EnvironmentFile 能够指定 etcd 的配置文件。在我这里由于只是测试安装,因此 etcd 使用默认配置就能够了。安全
经过 systemd 启动 etcd 并设置为开机自启动bash
sudo systemctl daemon-reload sudo systemctl start etcd sudo systemctl enable etcd # 完成后能够检查一下服务是否正常运行 systemctl status etcd # 也可使用 etcdctl 来检查 etcd 健康情况 etcdctl cluster-health # 正常的输出为: # member 8e9e05c52164694d is healthy: got healthy result from http://localhost:2379 # cluster is healthy
tar xf kubernetes-server-linux-amd64.tar.gz # 将 kube-apiserver、kube-controller-manager 和 kube-scheduler 的二进制文件复制到 /usr/bin 目录下 sudo cp kubernetes/server/bin/kube-{apiserver,controller-manager,scheduler} /usr/bin/
编辑 systemd 服务文件 /lib/systemd/system/kube-apiserver.service
[Unit] Description=Kubernetes API Server After=etcd.service Wants=etcd.service [Service] EnvironmentFile=/etc/kubernetes/apiserver ExecStart=/usr/bin/kube-apiserver $KUBE_API_ARGS Restart=on-failure Type=notify LimitNOFILE=65536 [Install] WantedBy=multi-user.target
环境变量文件 /etc/kubernetes/apiserver 中定义了 kube-apiserver 启动参数 KUBE_API_ARGS。咱们建立这个文件并填入以下内容
KUBE_API_ARGS="--storage-backend=etcd3 --etcd-servers=http://127.0.0.1:2379 \ --insecure-bind-address=0.0.0.0 --insecure-port=8080 \ --service-cluster-ip-range=169.169.0.0/16 --service-node-port-range=1-65535 \ --admission_control=NamespaceLifecycle,LimitRanger,ServiceAccount, \ DefaultStorageClass,ResourceQuota \ --logtostderr=false --log-dir=/var/log/kubernetes --v=2"
参数说明:
--storage-backend :指定 etcd 版本。
--etcd-servers :指定 etcd 服务器地址和端口。
--insecure-bind-address :指定 api-server 非安全方式绑定的地址。0.0.0.0 表示全部地址。
--insecure-port :指定 api-server 非安全方式启用的端口号。
--service-cluster-ip-range :指定集群 Cluster IP 网段,若是后续须要使用网络插件这里须要按照网络插件要求的网段配置。
--service-node-port-range :指定集群中 Service 能够映射物理机端口号范围
--admission_control :Kubernetes 集群的准入控制设置,各控制模块以插件形式依次生效。
--logtostderr :指定为 false 时将错误日志写入日志文件而非 标准输出。
--log-dir :日志保存路径。
--v :日志级别
经过 systemd 启动 kube-apiserver 并设置为开机自启动
sudo systemctl daemon-reload sudo systemctl start kube-apiserver sudo systemctl enable kube-apiserver # 以后能够经过 status 来检查服务器运行状态 systemctl status kube-apiserver
编辑 systemd 服务文件 /lib/systemd/system/kube-controller-manager.service
[Unit] Description=Kubernetes Controller Manager After=kube-apiserver.service Requires=kube-apiserver.service [Service] EnvironmentFile=/etc/kubernetes/controller-manager ExecStart=/usr/bin/kube-controller-manager $KUBE_CONTROLLER_MANAGER_ARGS Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target
环境变量文件 /etc/kubernetes/controller-manager 中定义了 kube-controller-manager 启动参数 KUBE_CONTROLLER_MANAGER_ARGS。咱们建立这个文件并填入以下内容
KUBE_CONTROLLER_MANAGER_ARGS="--master=http://192.168.112.148:8080 \ --logtostderr=false \ --log-dir=/var/log/kubernetes \ --v=2"
参数说明:--master :指定 API-server 的URL地址
编辑 systemd 服务文件 /lib/systemd/system/kube-scheduler.service
[Unit] Description=Kubernetes Scheduler Server After=kube-apiserver.service Requires=kube-apiserver.service [Service] EnvironmentFile=/etc/kubernetes/scheduler ExecStart=/usr/bin/kube-scheduler $KUBE_SCHEDULER_ARGS Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target
环境变量文件 /etc/kubernetes/scheduler 中定义了 kube-scheduler 启动参数 KUBE_SCHEDULER_ARGS。咱们建立这个文件并填入以下内容
KUBE_SCHEDULER_ARGS="--master=http://192.168.112.148:8080 \ --logtostderr=false \ --log-dir=/var/log/kubernetes \ --v=2"
安装完 kube-controller-manager 和 kube-scheduler 以后将其启动并设置为开机自启动
sudo systemctl daemon-reload sudo systemctl start kube-controller-manager kube-scheduler sudo systemctl enable kube-controller-manager kube-scheduler # 一样,启动以后能够经过 systemctl status XXXX 来检查服务的状态 systemctl status kube-controller-manager systemctl status kube-scheduler.service
master 上的安装已经完成,下一步就要开始安装 node 节点上须要的服务了。
node 节点上须要安装的服务有 docker 、kubelet 和 kube-proxy。
安装 docker 的方式不少,在这里我使用添加阿里云的源并使用 apt-get 安装:
# step 1: 安装必要的一些系统工具 sudo apt-get update sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common # step 2: 安装GPG证书 curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add - # Step 3: 写入软件源信息 sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" # Step 4: 更新并安装 Docker-CE sudo apt-get -y update sudo apt-get -y install docker-ce
按装好后 docker 就是启动状态而且设置了开机自启。
tar xf kubernetes-server-linux-amd64.tar.gz # 将 kubelet 和 kube-proxy 的二进制文件复制到 /usr/bin 目录下 sudo cp kubernetes/server/bin/kube{let,-proxy} /usr/bin/
编辑 systemd 服务文件 /lib/systemd/system/kubelet.service
[Unit] Description=Kubernetes Kubelet Server After=docker.service Requires=docker.service [Service] WorkingDirectory=/var/lib/kubelet EnvironmentFile=/etc/kubernetes/kubelet ExecStart=/usr/bin/kubelet $KUBELET_ARGS Restart=on-failure [Install] WantedBy=mulit-user.target
WorkingDirectory 指定的路径是 kubelet 的数据目录,须要在服务运行前建立提早建立。
环境变量文件 /etc/kubernetes/kubelet 中定义了 kubelet 启动参数 KUBELET_ARGS。咱们建立这个文件并填入以下内容
KUBELET_ARGS="--api-servers=http://192.168.112.148:8080 \ --hostname-override=u16-2 \ --logtostderr=false \ --log-dir=/var/log/kubernetes \ --v=2"
参数说明:--api-servers :指定 apiserver 的URL地址。
--hostname-override :指定注册到 apiserver 时本节点的名称。
经过 systemd 启动 kubelet 并设置为开机自启动
sudo systemctl daemon-reload sudo systemctl start kubelet sudo systemctl enable kubelet # 以后能够经过 status 来检查服务器运行状态 systemctl status kubelet
编辑 systemd 服务文件 /lib/systemd/system/kube-proxy.service
[Unit] Description=Kubernetes Kube-Proxy Server After=networking.service Requires=networking.service [Service] EnvironmentFile=/etc/kubernetes/proxy ExecStart=/usr/bin/kube-proxy $KUBE_PROXY_ARGS Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target
环境变量文件 /etc/kubernetes/proxy 中定义了 kube-proxy 启动参数 KUBE_PROXY_ARGS。咱们建立这个文件并填入以下内容
KUBE_PROXY_ARGS="--master=http://192.168.112.148:8080 \ --logtostderr=false \ --log-dir=/var/log/kubernetes \ --v=2"
经过 systemd 启动 kubu-proxy 并设置为开机自启动
sudo systemctl daemon-reload sudo systemctl start kube-proxy sudo systemctl enable kube-proxy # 以后能够经过 status 来检查服务器运行状态 systemctl status kube-proxy
node 节点设置完成后, 若是 master 节点上有 kubernetes 的命令行管理软件 kubectl ,就可使用kubectl 查看到新增长的节点。kubectl 的二进制文件能够从 kubernetes-server-linux-amd64.tar.gz 中找到。
sudo cp kubernetes/server/bin/kubectl /usr/bin/ sudo chmod +x /usr/bin/kubectl kubectl get node # 输出为 # NAME STATUS AGE VERSION # u16-2 NotReady 17m v1.6.0
这时能够看到新增长的节点 u16-2 的状态为 NotReady,经过命令来查看 node 状态
kubectl describe node u16-2
这时能够在 Events: 中看到一条报错,Massage是
Failed to start ContainerManager failed to initialise top level QOS containers: root container /kubepods doesn't exist
解决办法参考这里,在kubelet 的启动参数中加上下面参数并重启
--cgroups-per-qos=false --enforce-node-allocatable=""
重启后 node 变为 Ready 状态。
# 在集群上运行 kubernetes-bootcamp 镜像 kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1 --port=8080 # 由于上面命令中的镜像位置在国内可能也没法正常访问 因此能够将其替换为 dockerhub 上相同的镜像 jocatalin/kubernetes-bootcamp:v1 kubectl run kubernetes-bootcamp --image=jocatalin/kubernetes-bootcamp:v1 --port=8080 # 检查 deployment 运行状态 kubectl get deployment # ---显示以下--- NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE kubernetes-bootcamp 1 0 0 0 4m # 当前的 Pod 数一直为0,检查一下 deployment 状态 kubectl describe deployment kubernetes-bootcamp # Events 中最后的信息为 Scaled up replica set kubernetes-bootcamp-4025819334 to 1 ,再看一下 replicaSet 的状态 kubectl describe replicaset kubernetes-bootcamp-4025819334
发现 Events 中的报错:
Error creating: No API token found for service account "default", retry after the token is automatically created and added to the service account
解决方法参考这里,由于这里搭建的整个集群都是无安全认证的,因此将 api-server 中的 --admission_control 参数里的 ServiceAccount 删除,并重启 kube-apiserver 。
以后再次查看 deployment 状态
kubectl get deployment # ---显示以下--- NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE kubernetes-bootcamp 1 1 1 0 18m
此次 pod 成功建立了,但仍然不是 AVAILABLE 状态。
# 查看现有的 pod kubectl get pod # ---显示以下--- NAME READY STATUS RESTARTS AGE kubernetes-bootcamp-4025819334-q61xj 0/1 ContainerCreating 0 5m # 查看这个 Pod 的详细信息 kubectl describe pod kubernetes-bootcamp-4025819334-q61xj # 在Events 里看到了错误信息: # Error syncing pod, skipping: failed to "CreatePodSandbox" for "kubernetes-bootcamp-4025819334-q61xj_default(1d20e7af-af48-11e8-bf2f-000c29a01556)" with CreatePodSandboxError: "CreatePodSandbox for pod \"kubernetes-bootcamp-4025819334-q61xj_default(1d20e7af-af48-11e8-bf2f-000c29a01556)\" failed: rpc error: code = 2 desc = unable to pull sandbox image \"gcr.io/google_containers/pause-amd64:3.0\": Error response from daemon: {\"message\":\"Get https://gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)\"}"
根据信息可知错误是由于下载这个镜像失败:gcr.io/google_containers/pause-amd64:3.0 。仍是网络环境的问题,这时能够在 dockerhub 上找到相同的镜像下载并修改 tag 来获得这个镜像。
在 node 节点上执行
sudo docker image pull mirrorgooglecontainers/pause-amd64:3.0 sudo docker tag mirrorgooglecontainers/pause-amd64:3.0 gcr.io/google_containers/pause-amd64:3.0
镜像下载好以后再次查看 deployment 状态:
kubectl get deployment # ---显示以下--- NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE kubernetes-bootcamp 1 1 1 1 35m
此时服务已经部署正确,为了集群外部也可以访问到服务,如今须要使用 NodePort 方式将端口暴露出来。
kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080 kubectl get service # ---输出以下--- NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes 169.169.0.1 <none> 443/TCP 2d kubernetes-bootcamp 169.169.210.120 <nodes> 8080:10412/TCP 12m
此时 node 上的 10412 端口已经打开(这里的 10412 端口是在 kube-apiserver 启动参数 --service-node-port-range 范围内随机分配的),而且在 node 本机上是能够访问的。可是集群外部访问就会超时,包括没有安装 kube-proxy 的 master 访问也会超时。解决办法参考这里。
为了安全起见, docker 在 1.13 版本以后,将系统iptables 中 FORWARD 链的默认策略设置为 DROP,并为链接到 docker0 网桥的容器添加了放行规则。
知道了缘由是 docker 启动时修改了iptables 规则后,能够修改 docker 的服务文件 /lib/systemd/system/docker.service 添加下面内容
ExecStartPost=/sbin/iptables -P FORWARD ACCEPT
含义为在启动 docker 以后,修改 FORWARD 链的默认规则为 ACCEPT。配置完成以后重启 docker 。此时外部就能够访问了。
至此,一个单 master 单 node 的非安全 kubernets 集群已经配置完成,而且基础功能能够正常使用。