kubernetes 搭建手册

本文档为内部的 Kubernetes 以及基础组件安装手册,你可以将它视作基础组件的安装规范。因此,安装过程中应严格按照本手册操作。

本文仅包含安装步骤,不会关注于组件介绍、名词解释或概念科普等内容。但是不排除会提供一些超链接,可以将你导航到更加详细的科普文档,这些文档里可能会提供一些安装步骤,但是请你以本文的安装步骤为准。

关于信任的基础组件列表,请参考组件列表,也就是说,在生产环境中,禁止引入本手册以外的组件。如确有必要,我们会在测试环境充分验证后,加入本文档。

组件列表

  • 配置管理:etcd
  • docker
  • kubernetes
  • 网络插件:flannel
  • ntp 服务:chrony
  • ingress:traefix
  • 负载均衡:haproxy + keepalived
  • dashboard:kuboard + kubernetes dashboard
  • 监控:prometheus + grafana
  • 日志:loki
  • 配置中心:nacos
  • 持久化存储:ceph

安装工具列表

准备 & 规划

升级内核

Kubernetes 各节点升级内核版本,内核下载地址:https://kernel.ubuntu.com/~kernel-ppa/mainline/

建议内核版本:

  • ubuntu16.04 - 4.15.18
  • ubuntu18.04 - 4.20.17

准备安装环境

在一台能够访问互联网的服务器作为控制机,并执行以下动作。

安装包管理器

  1. # 安装 Helm
  2. SCRIPT_PATH=$(pwd)
  3. HOST="http://file.topvdn.com/containers/helm"
  4. OS=$(uname -s | tr A-Z a-z)
  5. ARCH="amd64"
  6. NAME="helm"
  7. VERSION="$(curl -sSL ${HOST}/stable.txt)"
  8. SUFFIX="tar.gz"
  9. FILENAME="${NAME}-${VERSION}-${OS}-${ARCH}.${SUFFIX}"
  10. BIN_DIR="/usr/local/bin"
  11. mkdir -p ${BIN_DIR}
  12. curl -Lo /tmp/${FILENAME} ${HOST}/${FILENAME} && cd /tmp && tar xf ${FILENAME} && install /tmp/${OS}-${ARCH}/${NAME} ${BIN_DIR}/${NAME} && rm -r /tmp/${OS}-${ARCH} && rm ${FILENAME}
  13. cd ${SCRIPT_PATH}
  14. # 删除默认 repo
  15. for r in `helm repo list | awk '{print $1}' | sed '1d'`; do helm repo remove $r; done
  16. # 添加私有 repo,用户名、密码找运维部获取
  17. helm repo add topvdn https://harbor.topvdn.com/chartrepo/private --username <username> --password <password>
  18. # 更新软件包列表
  19. helm repo update

离线文件准备脚本

  1. # 克隆安装脚本仓库
  2. git clone http://git.topvdn.com/lingda_ops/kubeasz_init.git

离线文件准备

如选择在线安装,可以跳过此步骤,直接开始规划
下载好离线文件以后,将/etc/ansible目录打包,传输到需要部署环境内的一台机器上即可。

在同一台服务器上执行事先准备好的脚本:

  1. cd kubeasz_init
  2. # 下载离线镜像、二进制文件,在线安装可省略
  3. bash easzup_2.2.1 -D
  4. # 下载离线系统软件包,在线安装可省略
  5. bash easzup_2.2.1 -P

easzup_<version>脚本第23行可修改离线文件存放的私有 docker 仓库地址,通常不需要修改。特殊情况下,如公司内网部署,将此处修改为内网私有仓库地址,会显著提高下载速度。

执行成功后,所有文件均已整理好放入目录/etc/ansible,只要把该目录整体复制到任何离线的机器上,即可开始安装集群,离线文件包括:

  • /etc/ansible包含 kubeasz 版本为 ${release} 的发布代码
  • /etc/ansible/bin包含 k8s/etcd/docker/cni 等二进制文件
  • /etc/ansible/down包含集群安装时需要的离线容器镜像
  • /etc/ansible/down/packages包含集群安装时需要的系统基础软件

离线文件不包括:

  • 管理端 ansible 安装,但可以使用 kubeasz 容器运行 ansible 脚本
  • 其他更多 kubernetes 插件镜像

设置离线参数

  1. # 设置参数允许离线安装,在线安装可省略
  2. sed -i 's/^INSTALL_SOURCE.*$/INSTALL_SOURCE: "offline"/g' /etc/ansible/roles/chrony/defaults/main.yml
  3. sed -i 's/^INSTALL_SOURCE.*$/INSTALL_SOURCE: "offline"/g' /etc/ansible/roles/ex-lb/defaults/main.yml
  4. sed -i 's/^INSTALL_SOURCE.*$/INSTALL_SOURCE: "offline"/g' /etc/ansible/roles/kube-node/defaults/main.yml
  5. sed -i 's/^INSTALL_SOURCE.*$/INSTALL_SOURCE: "offline"/g' /etc/ansible/roles/prepare/defaults/main.yml

规划

  1. cd /etc/ansible
  2. # 以下样本文件根据实际情况二选一
  3. # 单机
  4. cp example/hosts.allinone hosts
  5. # 集群
  6. cp example/hosts.multi-node hosts
  7. # 根据实际情况修改配置,通常只需要修改 ip 地址
  8. vi hosts

配置 ssh 免密

自动化部署基于 ansible,因此需要配置控制机到 kubernetes 集群内机器的 ssh 免密登录。

方法:略

安装

kubernetes 套件

此步骤会安装 etcd、docker、kubernetes、flannel、chrony。

控制机上执行以下命令:

  1. # 启动 kubeasz 容器,包含安装代码和代码的运行环境
  2. ./easzup -S
  3. docker exec -it kubeasz /bin/bash
  4. cd /etc/ansible
  5. # 如果修改了 ssh 服务的默认端口,需要修改全局的连接配置
  6. # SSH_PORT=<ssh_port>
  7. # mkdir group_vars && echo "ansible_ssh_port: $SSH_PORT" > group_vars/all
  8. # 测试连通性
  9. ansible all -m ping
  10. # 以下两种安装方式二选一
  11. # 一步安装
  12. ansible-playbook 90.setup.yml
  13. # 分步安装
  14. ansible-playbook 01.prepare.yml
  15. ansible-playbook 02.etcd.yml
  16. ansible-playbook 03.docker.yml
  17. ansible-playbook 04.kube-master.yml
  18. ansible-playbook 05.kube-node.yml
  19. ansible-playbook 06.network.yml
  20. ansible-playbook 07.cluster-addon.yml

验证方法:

  1. # 查看节点状态
  2. kubectl get nodes
  3. # 查看 pod 状态
  4. kubectl get pods -A

持久化存储

持久化存储使用 ceph,目前只支持在线安装。

本例使用一台单独的控制机,部署由6个节点组成的 ceph 集群,并使用单独的业务网络集群网络隔离不同类型的网络流量,避免集群内的流量对业务造成影响。

基础安装

配置业务网络 hosts 解析

包括 ceph 集群各节点和控制机,都需要配置 ceph 集群内各节点主机名到业务网络 IP 地址的静态解析。

  1. $ cat /etc/hosts
  2. 192.168.2.1 ops-ceph1
  3. 192.168.2.2 ops-ceph2
  4. 192.168.2.3 ops-ceph3
  5. 192.168.2.4 ops-ceph4
  6. 192.168.2.5 ops-ceph5
  7. 192.168.2.6 ops-ceph6

配置 ssh 免密登录

后续步骤用到的部署工具需要通过 ssh 连接 ceph 集群内各节点,所以需要配置控制机到 ceph 集群内机器的 ssh 免密登录。

方法:略

部署工具无法修改 ssh 端口,因此,如果修改了 ssh 服务的默认监听端口,则需要临时开启 ssh 的22端口监听。

添加 ceph 仓库

ceph 集群各节点、控制机kubernetes 集群所有节点都需要添加 ceph 软件仓库。

  1. wget -q -O- 'https://mirrors.aliyun.com/ceph/keys/release.asc' | sudo apt-key add -
  2. ceph_stable_release=octopus
  3. echo deb https://mirrors.aliyun.com/ceph/debian-$ceph_stable_release/ $(lsb_release -sc) main | sudo tee /etc/apt/sources.list.d/ceph.list

安装部署工具

控制机安装部署工具:ceph-deploy

  1. apt update && apt install -y ceph-deploy

安装客户端

kubernetes 要使用 ceph 持久化存储,必须安装 ceph 客户端软件。

  1. apt update && apt install -y ceph-common

ceph 集群部署

集群部署全部在控制机上操作。

创建一个集群
  1. # 生产环境通常至少3个 mon 节点
  2. $ ceph-deploy new --public-network 192.168.2.0/24 --cluster-network 172.16.0.0/24 ops-ceph1 ops-ceph3 ops-ceph5
  3. $ cat ceph.conf
  4. [global]
  5. fsid = de898995-8362-4a7f-80f2-ce502710d7a0
  6. public_network = 192.168.2.0/24
  7. cluster_network = 172.16.0.0/24
  8. mon_initial_members = ops-ceph1, ops-ceph3, ops-ceph5
  9. mon_host = 192.168.2.112,192.168.2.114,192.168.2.116
  10. auth_cluster_required = cephx
  11. auth_service_required = cephx
  12. auth_client_required = cephx
  • 可以在 ceph 配置文件里的默认副本数从 3 改成 2 ,这样只有两个 OSD 也可以达到 active + clean 状态。把下面这行加入 [global]段:
  1. osd_pool_default_size = 2

ceph 组件安装
  1. # 该命令应包含所有 ceph 节点
  2. ceph-deploy install --no-adjust-repos ops-ceph1 ops-ceph2 ops-ceph3 ops-ceph4 ops-ceph5 ops-ceph6

初始化监控节点并收集 keyring
  1. ceph-deploy mon create-initial

创建 mgr 节点
  1. # 生产环境通常至少3个 mgr 节点
  2. ceph-deploy mgr create ops-ceph1 ops-ceph3 ops-ceph5

添加 osd 节点
  1. ceph-deploy osd create ops-ceph1 --data /dev/sdn
  2. ceph-deploy osd create ops-ceph2 --data /dev/sdn
  3. ceph-deploy osd create ops-ceph3 --data /dev/sdn
  4. ceph-deploy osd create ops-ceph4 --data /dev/sdn
  5. ceph-deploy osd create ops-ceph5 --data /dev/sdn
  6. ceph-deploy osd create ops-ceph6 --data /dev/sdn

创建 mds 节点(cephfs 功能)
  1. # 安装 mds 到与 mgr 节点相同的机器上
  2. ceph-deploy mds create ops-ceph1 ops-ceph3 ops-ceph5

验证

控制机并没有安装 ceph,ceph 相关命令无法在控制机上执行。因此,需要将安装过程中生成的一系列 key 文件拷贝到 ceph 集群节点上,使之有权限进行容器管理。

  1. # 控制机执行
  2. scp ceph*keyring ops-ceph1:/etc/ceph
  1. # ops-ceph1节点执行
  2. # 查看集群状态
  3. ceph -s
  4. # 查看仲裁
  5. ceph quorum_status --format json-pretty
  6. # 查看 mon 状态
  7. ceph mon stat
  8. ceph mon dump

启用/禁用 Dashboard
  • 生产环境慎用
  • 使用强密码
  1. # 启用仪表板模块
  2. ceph mgr module enable dashboard
  3. # 生成自签证书
  4. ceph dashboard create-self-signed-cert
  5. # 设置账号密码,协议 https,端口8443
  6. ceph dashboard set-login-credentials 'admin' 'fhe8792ofdih'
  7. # 禁用仪表盘模块
  8. ceph mgr module disable dashboard

配置

ceph 管理节点上运行
  • 创建 pool
    pg_num 的值要根据 OSD 的数量进行调整,计算公式是:Total PGs = (Total_number_of_OSD * 100) / max_replication_count,但是最后算出的结果一定要接近或者等于一个2的指数。
    本例有6个 OSD,因此设置pg_num为256:
  1. # 创建 cephrbd 的 pool
  2. ceph osd pool create kube 256
  3. # 创建 cephfs 的数据和元数据两个 pool
  4. ceph osd pool create cephfs_data 256 256
  5. ceph osd pool create cephfs_meta 256 256
  6. # 使用已创建的元数据和数据池创建一个新的 ceph 文件系统,名为 cephfs
  7. ceph fs new cephfs cephfs_meta cephfs_data
  8. # 查看 cephfs 信息
  9. ceph fs ls
  • 创建 k8s 访问 ceph 的用户
  1. ceph auth get-or-create client.kube mon 'allow r' osd 'allow class-read object_prefix rbd_children, allow rwx pool=kube'
  • 查看 key
  1. $ ceph auth get-key client.admin
  2. AQCmJL5f5fRzJRAAKmPqhND42loXoxvtQF1dYw==
  3. $ ceph auth get-key client.kube
  4. AQADTb5fYCJMFBAAgZO1GFTrC5OLHYsST2a1Ew==

控制机上执行
  • 创建 secret
  1. # 创建 admin 的 secret
  2. kubectl create secret generic ceph-secret --type="kubernetes.io/rbd" -n kube-system \
  3. --from-literal=key=AQCmJL5f5fRzJRAAKmPqhND42loXoxvtQF1dYw==
  4. # 创建 pvc 用于访问 ceph 的 secret
  5. kubectl create secret generic ceph-user-secret --type="kubernetes.io/rbd" \
  6. --from-literal=key=AQADTb5fYCJMFBAAgZO1GFTrC5OLHYsST2a1Ew==
  • 配置 StorageClass
  1. $ vim storageclass-ceph-rdb.yaml
  2. kind: StorageClass
  3. apiVersion: storage.k8s.io/v1
  4. metadata:
  5. name: ceph-block
  6. provisioner: kubernetes.io/rbd
  7. parameters:
  8. monitors: 192.168.2.1:6789,192.168.2.3:6789,192.168.2.5:6789 # 填写全部 mon 实例
  9. adminId: admin
  10. adminSecretName: ceph-secret
  11. adminSecretNamespace: kube-system
  12. pool: kube
  13. userId: kube
  14. userSecretName: ceph-user-secret
  15. fsType: ext4
  16. imageFormat: "2"
  17. imageFeatures: "layering"
  18. $ kubectl apply -f storageclass-ceph-rdb.yaml
  19. storageclass.storage.k8s.io/ceph-block created
  20. $ kubectl get sc
  21. NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
  22. ceph-block kubernetes.io/rbd Delete Immediate false 18s

负载均衡

  1. ansible-playbook /etc/ansible/roles/ex-lb/ex-lb.yml

ingress

  1. # 安装 traefik
  2. helm upgrade --install -n kube-system -f chart_values/traefik-settings.yaml traefik topvdn/traefik
  3. # 创建 traefik middleware
  4. kubectl apply -f manifests/traefik-middleware/redirect-https.yaml
  5. # 访问 dashboard
  6. ## forward dashboard port
  7. kubectl -n kube-system port-forward --address 0.0.0.0 $(kubectl get pods --selector "app.kubernetes.io/name=traefik" --output=name -n kube-system) 9000:9000
  8. ## 获取访问方式
  9. echo http://$(hostname -I | awk '{print $1}'):9000/dashboard/

dashboard

  • 官方 dashboard
  1. # 查看 NodePort 端口
  2. $ kubectl get svc -n kube-system | grep dashboard
  3. kubernetes-dashboard NodePort 10.68.125.217 <none> 443:32436/TCP 350d
  4. # 可以看到,dashboard的NodePort端口是 32436,访问 https://<任意节点ip>:<NodePort> 即可打开 dashboard。
  5. # 查看登录令牌
  6. $ kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')`
  • kuboard - 国产控制台,推荐
  1. # 创建证书 secret (kube-system 命名空间)
  2. kubectl create -n kube-system secret tls antelopecloud.cn-tls \
  3. --cert=STAR.antelopecloud.cn.crt --key=STAR.antelopecloud.cn.key
  4. # 安装
  5. helm upgrade --install -n kube-system kuboard topvdn/kuboard \
  6. --set ingress.enabled=True --set ingress.hosts[0]=tz-ops.antelopecloud.cn \
  7. --set ingress.tlsEnabled=True --set ingress.tls[0].secretName=antelopecloud.cn-tls
  8. # 查看访问 URL 和 token
  9. helm -n kube-system status kuboard

日志

  1. helm upgrade --install -n kube-public -f chart_values/loki-settings.yaml loki topvdn/loki
  2. helm upgrade --install -n kube-public promtail topvdn/promtail --set "loki.serviceName=loki"

监控

以下域名域名证书文件需自行准备,并修改。

  • 创建 namespace
  1. kubectl create ns monitor
  • 安装 prometheus
  1. helm upgrade --install -n monitor -f chart_values/prometheus-settings.yaml prometheus topvdn/prometheus
  • 安装 grafana
  1. # 创建证书 secret(monitor 命名空间)
  2. kubectl create -n monitor secret tls antelopecloud.cn-tls \
  3. --cert=STAR.antelopecloud.cn.crt --key=STAR.antelopecloud.cn.key
  4. # 安装或更新 grafana
  5. helm upgrade grafana topvdn/grafana --install -n monitor -f chart_values/grafana-settings.yaml \
  6. --set ingress.enabled=True \
  7. --set ingress.hosts[0]=tz-ops.antelopecloud.cn \
  8. --set ingress.tls[0].secretName=antelopecloud.cn-tls
  9. # 创建 http 到 https 跳转
  10. sed 's/<HOST>/tz-ops.antelopecloud.cn/' manifests/grafana-ingress-http.yaml | kubectl apply -f -
  11. # 创建 dashboard
  12. kubectl -n monitor create configmap dashboard-prometheus --from-file=prometheus.json=dashboard_grafana/Prometheus自监控大盘.json
  13. kubectl -n monitor label configmap dashboard-prometheus grafana_dashboard="1"
  14. kubectl -n monitor create configmap dashboard-mysql --from-file=prometheus.json=dashboard_grafana/mysql监控大盘.json
  15. kubectl -n monitor label configmap dashboard-mysql grafana_dashboard="1"
  16. kubectl -n monitor create configmap dashboard-nacos --from-file=prometheus.json=dashboard_grafana/Nacos监控大盘.json
  17. kubectl -n monitor label configmap dashboard-nacos grafana_dashboard="1"
  1. export POD_NAME=$(kubectl get pods --namespace monitor -l "app=prometheus,component=server" -o jsonpath="{.items[0].metadata.name}")
  2. kubectl --namespace monitor --address 0.0.0.0 port-forward $POD_NAME 9090
  3. ## 获取访问方式
  4. echo http://$(hostname -I | awk '{print $1}'):9090
  • alertmanager
  1. export POD_NAME=$(kubectl get pods --namespace monitor -l "app=prometheus,component=alertmanager" -o jsonpath="{.items[0].metadata.name}")
  2. kubectl --namespace monitor --address 0.0.0.0 port-forward $POD_NAME 9093
  3. ## 获取访问方式
  4. echo http://$(hostname -I | awk '{print $1}'):9093

配置中心

  • 安装mysql
  1. helm upgrade --install -n kube-public -f chart_values/mysql-settings.yaml mysql topvdn/mysql
  • 安装nacos
  1. # 获取 mysql 密码
  2. MYSQL_ROOT_PASSWORD=$(kubectl get secret -n kube-public mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)
  3. # 安装,根据实际情况修改 ingress.hosts.host
  4. helm upgrade --install -n kube-public -f chart_values/nacos-settings.yaml \
  5. --set ingress.hosts.host=nacos.lingda.com \
  6. --set mysql.rootPassword=$MYSQL_ROOT_PASSWORD \
  7. nacos topvdn/nacos
  8. # 获取 nacos 登录方式
  9. helm -n kube-public status nacos

配置

导入 nacos 配置

  1. # 从仓库拉取配置模板和变量模板
  2. git clone ssh://git@42.51.12.153:10022/lingda_ops/lm_conf_generator.git -b ${版本号:0.6.0}
  3. # 使用port-forward映射nacos网站
  4. kubectl port-forward -n kube-public nacos-0 8848:8848 --address 0.0.0.0
  5. # 使用二进制工具导入
  6. ## 首先登录之前映射的nacos网站
  7. nacosctl login 127.0.0.1 -p 8848
  8. ## 查询命名空间确认需要导入的空间id
  9. nacosctl get ns
  10. ## 渲染配置模板与变量,输出到命令行,进行检查
  11. nacosctl gen -f ../../lm_conf_generator/config/tz-pre.ini -t ../../lm_conf_generator/templates --st
  12. ## 将渲染的变量输出到指定目录
  13. nacosctl gen -f ../../lm_conf_generator/config/tz-pre.ini -t ../../lm_conf_generator/templates -o ./conf
  14. ## 将生成的配置导入nacos
  15. nacosctl import all -d ./conf -n pro -u 127.0.0.1 -U nacos -P nacos -p 8848
  16. -----------------------------------------------------------------------------
  17. # 使用镜像工具导入
  18. ## 先登录(把nacos域名换成自环境域名,并使用账号密码登录)
  19. docker run -it --rm -v /tmp:/root/.nacos/ harbor.lingda.com/internal/nacosctl:1.1 nacosctl login 127.0.0.1 -p 8848
  20. ## 导入(导入前确保命名空间已经创建)
  21. ### 查询已创建的命名空间
  22. docker run -it --rm -v /opt:/opt harbor.lingda.com/internal/nacosctl:1.1 nacosctl get ns
  23. ### 渲染配置检查变量赋值
  24. docker run -it --rm -v /opt:/opt harbor.lingda.com/internal/nacosctl:1.1 nacosctl gen -f /opt/lm_conf_generator/config/tz-pre.ini -t /opt/lm_conf_generator/templates --st
  25. ## 将渲染的变量输出到指定目录
  26. docker run -it --rm -v /opt:/opt harbor.lingda.com/internal/nacosctl:1.1 nacosctl gen -f /opt/lm_conf_generator/config/tz-pre.ini -t /opt/lm_conf_generator/templates -o ./conf
  27. ## 将生成的配置导入nacos
  28. docker run -it --rm -v /opt:/opt harbor.lingda.com/internal/nacosctl:1.1 nacosctl import all -d ./conf -n pro -u 127.0.0.1 -U nacos -P nacos -p 8848
  29. > -n 指定命名空间
  30. > -G 指定公共配置项的group_name
  31. > -f 指定配置项目文件路径
  32. > -d 指定目录路径
  33. > -t 指定模板路径
  34. > -o 指定输出的目录地址
  35. > -u 指定网站
  36. > -p 指定网站端口
  37. > -U 指定网站用户
  38. > -P 指定网站密码
  39. > --st 命令行预览模式

资源