0%

Rancher 通过 vSphere 架设 Kubernetes 笔记

最近接触了 Kubernetes 的部署,最早看的是基于 ansible 的部署方案 https://github.com/easzlab/kubeasz,后经 leader 提示改看 rancher,发现 rancher 更加方便,遂作此文以记录。同时,此项目也值得一看 https://github.com/opsnull/follow-me-install-kubernetes-cluster

常用命令

  • 查看 Kubernetes 状态

kubectl version

正常应该显示

1
2
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.3", GitCommit:"5e53fd6bc17c0dec8434817e69b04a25d8ae0ff0", GitTreeState:"clean", BuildDate:"2019-06-07T09:55:27Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.5", GitCommit:"2166946f41b36dea2c4626f90a77706f426cdea2", GitTreeState:"clean", BuildDate:"2019-03-25T15:19:22Z", GoVersion:"go1.11.5", Compiler:"gc", Platform:"linux/amd64"}
  • 查看所有容器的状态

kubectl get pods --all-namespaces

  • 一次性测试工具,可以用于模拟基础容器内的环境,用完会自动删除

kubectl run --generator=run-pod/v1 test --rm -it --image=alpine /bin/sh

发布服务的注意点

硬盘

  • vSphere 下支持自动创建硬盘,但不支持扩大已经指定好的硬盘大小。因此指定最大硬盘大小时,可以尽可能给大。因为不会全部用完,是按需使用的。实测如果给 10Ti,那么初始会用掉 1Ti,之后缓慢增加

  • 需要在部署 Kubernetes 后,手工创建 StorageClass,具体命令参见 [部署步骤] - [vSphere] 一节

  • 发布需要存储的 docker 服务后,如果想删除,需要手工去 vSphere 的硬盘里自行删除自动创建的硬盘。这是因为 StorageClass 的 reclaimPolicy 被设置成了 Retain。这是为了避免移除服务时数据被自动清空

  • PersistentVolumeClaim 指定的 StorageClass 应为 eudicssd 或者 eudichdd,具体需要看情况按需使用

  • StatefulSet 如果设置了 replicas > 1,且配置了volumeClaimTemplates,那么新建的硬盘内是没有任何数据的。如果只是配置了 volumeClaim,那么 replicas > 1 时,第二个 Pod 创建会永远失败,因为目前 vSphere 的硬盘策略是只允许 ReadWriteOnce

亲和性调度

  • 对于硬件要求,可用性要求较高的服务,需要配置亲和性调度。避免 Kuberneters 将服务部署到硬件条件不足的 Node 上

  • Node 不可用后,会在大约5分钟后才调度到新的 Node 上,具体参见 https://kubernetes.io/zh/docs/concepts/architecture/nodes/

gRPC

  • 只能通过 NodePort 部署,不支持 Ingress,但由于 NodePort 的特性是会在每个 worker 上开同样的端口,因此问题不大,可以通过之前在 pfsense 里绑定的域名 test.local 直接访问

  • NodePort 端口范围: 30000-32767,可以在刚刚的 cloud-config.yml 里修改范围,但最好不要太低


部署

部署机器的最佳实践

  • 1 台运行 rancher 的机器,这台机器里不要部署 Kuberneters,因为 rancher 在部署 Kuberneters 时会新建许多 docker container,导致混乱

  • 3 台 etcd,其中硬盘最好给ssd,内存尽可能给多,因为 Kuberneters 内几乎所有数据都会存放在 etcd 节点里,它是维持高可用的必须条件。这 3 台最好分别位于不同的机器,避免一台主机的停止导致整个 Kuberneters 不可用

  • 2 台 master,最好分别位于不同的机器

  • 若干 worker

部署步骤

vSphere

  • 配置 deploy 机器,设定好 deploy 机器的 IP 地址,以及计算机名后,运行脚本 start_deploy.sh,脚本内容如下
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
70
71
72
73
ansible-playbook -i ./inventory playbook.yml

playbook.yml
- hosts: all
become: yes
remote_user: root
tasks:
- name: 删除原有dns
file:
path: /etc/resolv.conf
state: absent

- name: 软链接阻止重新生成
file:
path: /etc/resolv.conf
src: /run/systemd/resolve/resolv.conf
state: link

- name: 临时修改主机名
shell: hostname {{ inventory_hostname }}

- name: 永久修改主机名
lineinfile:
path: /etc/hostname
regexp: '.*'
line: "{{ inventory_hostname }}"

# - name: 配置每台主机的hosts(/etc/hosts),添加host_ip $hostname到/etc/hosts文件中
# template:
# src: hosts.j2
# dest: /etc/hosts
# mode: '0644'

- name: 关闭防火墙
shell: ufw disable

- name: 修改时区为国内
shell: ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

- name: apt-get update
shell: apt-get update

- name: Install packages to allow apt to use a repository over HTTPS
shell: apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common

- name: Add Docker’s official GPG key
shell: curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

- name: Verify
shell: apt-key fingerprint 0EBFCD88

- name: Additional install
shell: apt install apt-transport-https ca-certificates curl software-properties-common

- name: Additional key
shell: curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

- name: Additional responsity
shell: add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic test"

- name: apt-get update
shell: apt-get update

- name: set docker version
shell: apt-cache madison docker-ce|grep {{ DOCKER_VERSION }}|awk '{print $3}'
register: version

- name: final install
shell: apt-get install -y docker-ce={{ version.stdout }} --allow-downgrades

- name: start automatic
shell: systemctl enable docker

  • 通过 ssh 登录到 deploy 机器上,运行以下命令,假设 deploy 机器位于 192.168.1.199

docker run -d --restart=unless-stopped --name=rancher-server --log-driver json-file --log-opt max-size=5g -p 80:80 -p 443:443 -v 192.168.1.199:/var/lib/rancher/ -v /root/var/log/auditlog:/var/log/auditlog -e AUDIT_LEVEL=3 rancher/rancher:v2.2.4

  • 等待一段时间后在内网任意机器上,直接访问 https://192.168.1.199

  • 右上角头像账户 -> Cloud Credentials -> Add Cloud Credential,以下假设 vSphere 的地址为 192.168.1.140

Name: credential(可任意填)

Cloud Credential Type: VMware vSphere

vCenter or ESXi Server: 192.168.1.140

Port: 443

Username: ***

Password: ***

  • 点击 Create

  • 右上角头像账户 -> Node Template -> Add Template -> 选择 vSphere

  • Account Access 选择刚刚创建的 credential

  • Instance Options

配置按需填写

  • Scheduling

这里的填写模式,应该去看 vSphere Client -> Shortcuts -> Global Inventory Lists 里的详细列表。不要看 rancher 的提示

注意 HostPool 互斥,写了一个就不要写第二个

Folder: /rancher-k8s(指定虚拟机文件夹,仅是为了方便管理,可以不填)

  • 创建完毕一个 Node Template 后,可以按需要 Clone 多个,然后只是微调下硬件配置,或调整 Host 配置,以便达到开设不同硬件类型机器、强制部署不同主机的目的

  • 返回 rancher 首页,点击 Add Cluster,选择 vSphere

  • 按需设置 Node Pools,注意 Name Prefix 里不可以带下划线,建议使用 rancher-k8s-workerrancher-k8s-master 等。并且,按最佳实践,应该在刚刚一步 Clone 多个 Node Template,保证 etcd 位于不同机器,保证 master 位于不同机器。后续需要添加 Node 时,也是以不同的 Node Template 为单位新增的

  • 设置 Cluster Options

Kubernetes Version: 1.13.5-rancher1-3

Network Provider: Flannel (这种网络格式比较简单且稳定)

Cloud Provider: Custom,然后点击Edit,将本项目内的文件cloud-config.yml里的内容复制进去

注意部署完毕后,需要再次去检查 cloud-config.yml ,曾经遇到过 insecure_flag 被重新设置为 false 的情况,如果发生此情况则集群无法成功创建,需要重新 Edit Cluster。以下是 cloud-config.yml 内容

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
addon_job_timeout: 30
authentication:
strategy: "x509|webhook"
bastion_host:
ssh_agent_auth: false
cloud_provider:
name: "vsphere"
vsphereCloudProvider:
global:
insecure-flag: true
soap-roundtrip-count: 0
virtual_center:
192.168.1.140:
datacenters: "***"
soap-roundtrip-count: 0
user: ***
password: ***
workspace:
datacenter: "***"
default-datastore: "***"
folder: "***"
server: "192.168.1.140"
ignore_docker_version: true
ingress:
provider: "nginx"
kubernetes_version: "v1.13.5-rancher1-3"
monitoring:
provider: "metrics-server"
network:
options:
flannel_backend_type: "vxlan"
plugin: "flannel"
restore:
restore: false
services:
etcd:
backup_config:
enabled: true
interval_hours: 12
retention: 6
creation: "12h"
extra_args:
election-timeout: "5000"
heartbeat-interval: "500"
retention: "72h"
snapshot: false
kube-api:
always_pull_images: false
pod_security_policy: false
service_node_port_range: "30000-32767"
kubelet:
fail_swap_on: false
ssh_agent_auth: false
#
# # Rancher Config
#
docker_root_dir: "/var/lib/docker"
enable_cluster_alerting: false
enable_cluster_monitoring: false
enable_network_policy: false
local_cluster_auth_endpoint:
enabled: true
name: "rancher"

  • 点击 Create,进入首页 -> rancher -> Nodes,查看创建进程,可能需要等待数分钟。也可以登录到 deploy 机器,使用 docker logs rancher-server -f 命令,实时查看 rancher 当前的创建进度

  • 一旦修改集群配置,集群内所有服务将不可用,但添加Node节点不影响,尽可能避免删除Node节点

  • 当集群成功运行时,运行命令 kubectl apply -f ./k8s-storageclass.yaml(如果没有安装并配置 kubectl, 请参见后面的 [macOS 的配置] 一节),该命令会添加自动请求磁盘空间的 StorageClass: eudicssdeudichdd。可以让服务后续自由的选择硬盘性质

普通机器

  • 将需要部署的机器的IP地址全部填入 inventory 文件的 [deploy] 下,这些机器必须满足能够在本机直接免密码登录root账户,且互相之间支持免密码登录root账户

  • 在 macOS 环境下,运行 start_deploy.sh 脚本。它需要 ansible 作为基础。如果没有 ansible,则可以 pip install ansible

  • start_deploy.sh 的作用是给每台机器配置可以完美运行 rancher 的环境,包括安装指定的 Docker、设定 Host 等

  • start_deploy.sh 是基于 Ubuntu 18.04 LTS 制作的

  • 如果后续需要添加新的机器,则这些新机器也必须要跑一遍 start_deploy.sh,然后再做下面的操作

  • 指定一台机器为运行 rancher的机器。在这台机器里运行以下指令,假设它位于 192.168.1.199

docker run -d --restart=unless-stopped -p 80:80 -p 443:443 -v 192.168.1.199:/var/lib/rancher/ -v /root/var/log/auditlog:/var/log/auditlog -e AUDIT_LEVEL=3 rancher/rancher:v2.2.4

  • 等待一段时间后直接访问 https://192.168.1.199

  • 点击 Add Cluster,选择 Custom

  • 设置 Cluster Options

Kubernetes Version: 1.13.5-rancher1-3

Network Provider: Flannel

  • 如果不是云服务器,保持 Cloud Provider 为空

  • 点击 Next

  • 此时会出现一段命令,需要手工选择节点的角色,会自动出现需要的命令,此时需要自己手工登录这些机器,并运行指定命令。Rancher 会自动检测内网里已运行命令的机器

  • 观察 rancher,直到所有 Node 状态都是已完成

外部服务发现的必要操作

由于目前常规服务(非 gRPC 服务)是通过 Ingress -> Service -> Deployment/StatefulSet -> Pod 的流程来找到具体的服务并发送接收流量的。Ingress 会根据域名来跳转。因此需要配置内置 DNS 服务,支持通配符匹配域名并跳转指定 IP,以下是 pfsense 的配置方法

需要注意的是:直接在 Host Overrides 里,让 Host 留空并只写 Parent domain of host 是无法起到通配符匹配的效果的

  • 进入 pfsense -> Services -> DNS Resolver -> General Settings -> Custom options

  • 在 Custom opptions 中输入以下内容,以便 test.local 的流量指向 worker

1
2
3
server:
local-zone: "test.local" redirect
local-data: "test.local 86400 IN A 192.168.1.226"

安装组件

Kubernetes Dashboard

  • 可以直接在 Rancher 的 App 内安装

  • 注意 Dashboard 必须安装在 System 命名空间内。可以打开 Enable Dashboard Cluster Admin Role,这样可以避免查询 Token 才能再次登录的问题

Helm(可选,暂时不需要)

  • 进入 Global,点击 Tools -> Catalogs,开启 Helm Stable,不开启 Helm Incubator,保证安装的都是 stable。

  • 安装 Helm CLI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
snap install helm --classic
kubectl -n kube-system create serviceaccount tiller

kubectl create clusterrolebinding tiller \
--clusterrole=cluster-admin \
--serviceaccount=kube-system:tiller

#helm init --service-account tiller

# Users in China: You will need to specify a specific tiller-image in order to initialize tiller.
# The list of tiller image tags are available here: https://dev.aliyun.com/detail.html?spm=5176.1972343.2.18.ErFNgC&repoId=62085.
# When initializing tiller, you'll need to pass in --tiller-image

helm init --service-account tiller --tiller-image registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.13.1
  • 完成后,做一下验证
    helm version

应该显示

1
2
3
4

Client: &version.Version{SemVer:"v2.14.0", GitCommit:"05811b84a3f93603dd6c2fcfe57944dfa7ab7fd0", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.13.1", GitCommit:"618447cbf203d147601b4b9bd7f8c37a5d39fbb4", GitTreeState:"clean"}

macOS 的配置

  • 安装 kubectl,这样可以本地运行 kubectl 直接部署需要的服务

brew install kubernetes-cli

  • 安装 kompose,这样可以将现存的 docker-compose.yml 直接转换成 Kubernetes 支持的 yaml

brew install kompose

  • 本地开设一个文件位于 ~/.kube/config,然后进入这里找到配置好的 config 文件: Cluster -> Kubeconfig File 内。配置成功后,本地调用 kubectl get nodes 进行验证。如果出现了服务器里的 nodes 则说明一切正常。

  • 注意在使用 kubectl 之前,必须确保关闭了Terminal代理(代理软件可以保持打开)。否则会反复报EOF错误。如有必要,运行以下命令清空环境变量

1
2
unset http_proxy
unset https_proxy

已知问题

  • 目前常规服务(非 gRPC 服务)是通过 Ingress -> Service -> Deployment/StatefulSet -> Pod 的流程来找到具体的服务并发送接收流量的。Ingress 会根据域名来跳转到合适的服务里,如果 pfsense 绑定的 IP 地址所在的 Node 不可用,那么将会导致域名解析到已经停止的机器上,进而导致服务无法访问。但实际上是可以访问的

  • 如果某个服务需要开设大量端口给 Kubernetes 外部使用,那么必须使用 NodePort 来实现,不太友好

  • 目前 Node 不可用后,需要等待 5 分钟才能调度该 Node 里的 Pod 到新的 Node 里去,时间太长

  • vSphere 不支持增大硬盘空间,一旦创建则不可修改。云服务则是可以的。目前只能通过指定较大的硬盘空间,来规避此问题

  • 目前创建会提示 Error creating machine: Error in driver during machine creation: The host does not have sufficient CPU resources to satisfy the reservation.