- k8s kubeasz安装k8s集群
- 集群规划和基础参数设定
- 机器准备
- 安装前准备
- 下载k8s集群所需的包和工具
- 创建证书和环境准备
- deploy 角色
- 创建 CA 证书
- 创建 CA 配置文件 ca-config.json.j2
- 创建 CA 证书签名请求 ca-csr.json.j2
- 生成CA 证书和私钥
- 生成 kubeconfig 配置文件
- 生成 admin 用户证书
- 生成 ~/.kube/config 配置文件
- 生成 kube-proxy.kubeconfig 配置文件
- 生成 system:kube-proxy 用户证书
- 生成 kube-proxy.kubeconfig
- 创建kube-controller-manager 和 kube-scheduler 组件的kubeconfig 文件
- prepare 角色
- 安装etcd集群
- 创建etcd证书
- 创建etcd 服务文件 etcd.service.j2
- 验证etcd集群状态
- 安装容器运行时
- 安装containerd
- kubeasz 集成安装 containerd
- 安装kube_master节点
- 高可用机制
- 安装流程
- 创建 kubernetes 证书签名请求
- 创建apiserver的服务配置文件
- 创建controller-manager 的服务文件
- 创建scheduler 的服务文件
- 在master 节点安装 node 服务: kubelet kube-proxy
- master 集群的验证
- 安装kube_node节点
- 创建cni 基础网络插件配置文件
- 创建 kubelet 的服务文件
- 创建 kube-proxy kubeconfig 文件
- 创建 kube-proxy服务文件
- 验证 node 状态
- 安装网络组件
- 安装讲解
- 安装集群主要插件
- 集群可选安装
- 安装脚本
- 集群规划和基础参数设定
k8s kubeasz安装k8s集群
参考官网:https://github.com/easzlab/kubeasz
集群规划和基础参数设定
机器准备
机器配置:
- master节点:4c/8g内存/50g硬盘
- worker节点:建议8c/32g内存/200g硬盘以上
注意:默认配置下容器运行时和kubelet会占用/var的磁盘空间,如果磁盘分区特殊,可以设置config.yml中的容器运行时和kubelet数据目录:CONTAINERD_STORAGE_DIR DOCKER_STORAGE_DIR KUBELET_ROOT_DIR
我这里机器有限,准备了4台机器,3台etcd节点复用了2台master节点和部署节点。留1台机器作为node节点:
192.168.61.82 //master节点,etcd节点,ansible节点
192.168.61.186 //master节点,etcd节点
192.168.58.134 //etcd节点
192.168.58.135 //node节点
安装前准备
- 确保各节点时区设置一致、时间同步。 如果你的环境没有提供NTP 时间同步,推荐集成安装chrony。参考单节点安装k8s集群的安装前准备工作 https://www.cnblogs.com/liwenchao1995/p/16279203.html
注意2:确保在干净的系统上开始安装,不要使用曾经装过kubeadm或其他k8s发行版的环境
注意3:建议操作系统升级到新的稳定内核,请结合阅读内核升级文档,参考 https://github.com/easzlab/kubeasz/blob/master/docs/guide/kernel_upgrade.md
注意4:在公有云上创建多主集群,请结合阅读在公有云上部署 kubeasz, 参考 https://github.com/easzlab/kubeasz/blob/master/docs/setup/kubeasz_on_public_cloud.md
//同时将各个节点的python版本升级为python3
python -V //升级文档可参考 https://www.cnblogs.com/liwenchao1995/p/16673676.html
//同时在ansible的那台机器192.168.61.82 ssh root@登陆其他机器,包括自己都要登陆一遍
ssh-keygen
ssh-copy-id [email protected]
...
下载k8s集群所需的包和工具
登陆ansible的那台机器,182.168.61.82,下载项目源码、二进制及离线镜像
下载工具脚本ezdown,举例使用kubeasz版本3.3.1
export release=3.3.1
wget https://github.com/easzlab/kubeasz/releases/download/${release}/ezdown
mv ezdown /usr/bin/;chmod +x /usr/bin/ezdown
下载kubeasz代码、二进制、默认容器镜像(更多关于ezdown的参数,运行./ezdown 查看)
# 国内环境
ezdown -D
# 海外环境
#ezdown -D -m standard
【可选】下载额外容器镜像(cilium,flannel,prometheus等)
ezdown -X
【可选】下载离线系统包 (适用于无法使用yum/apt仓库情形)
ezdown -P
上述脚本运行成功后,所有文件(kubeasz代码、二进制、离线镜像)均已整理好放入目录/etc/kubeasz
创建集群配置实例
//容器化运行kubeasz
ezdown -S
# 创建新集群 k8s-01
docker exec -it kubeasz ezctl new k8s-01
2021-01-19 10:48:23 DEBUG generate custom cluster files in /etc/kubeasz/clusters/k8s-01
2021-01-19 10:48:23 DEBUG set version of common plugins
2021-01-19 10:48:23 DEBUG cluster k8s-01: files successfully created.
2021-01-19 10:48:23 INFO next steps 1: to config '/etc/kubeasz/clusters/k8s-01/hosts'
2021-01-19 10:48:23 INFO next steps 2: to config '/etc/kubeasz/clusters/k8s-01/config.yml'
然后根据提示配置'/etc/kubeasz/clusters/k8s-01/hosts' 和 '/etc/kubeasz/clusters/k8s-01/config.yml':根据前面节点规划修改hosts 文件和其他集群层面的主要配置选项;其他集群组件等配置项可以在config.yml 文件中修改。
我修改了/etc/kubeasz/clusters/k8s-01/hosts的配置文件
[etcd]
192.168.61.82
192.168.61.186
192.168.58.134
# master node(s)
[kube_master]
192.168.61.82
192.168.61.186
# work node(s)
[kube_node]
192.168.58.135
开始安装 如果你对集群安装流程不熟悉,请阅读项目首页 安装步骤 讲解后分步安装,并对 每步都进行验证
#建议配置命令alias,方便执行
echo "alias dk='docker exec -it kubeasz'" >> /root/.bashrc
source /root/.bashrc
# 一键安装,等价于执行docker exec -it kubeasz ezctl setup k8s-01 all
dk ezctl setup k8s-01 all
# 或者分步安装,具体使用 dk ezctl help setup 查看分步安装帮助信息
# dk ezctl setup k8s-01 01
# dk ezctl setup k8s-01 02
# dk ezctl setup k8s-01 03
# dk ezctl setup k8s-01 04
...
ansible实际就是部署了一个镜像仓库,然后把所需要的镜像上传到镜像仓库里,然后ansible部署k8s集群
//ansible任务跑完后,查看刚刚创建的k8s集群
[16:16:20][root@yuanian-82:~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
192.168.58.135 Ready node 5m2s v1.24.2
192.168.61.186 Ready,SchedulingDisabled master 6m17s v1.24.2
192.168.61.82 Ready,SchedulingDisabled master 6m17s v1.24.2
创建证书和环境准备
- (optional) role:os-harden,可选系统加固,符合linux安全基线,详见upstream
- (optional) role:chrony,可选集群节点时间同步
- role:deploy,创建CA证书、集群组件访问apiserver所需的各种kubeconfig
- role:prepare,系统基础环境配置、分发CA证书、kubectl客户端安装
deploy 角色
主要任务讲解:roles/deploy/tasks/main.yml
创建 CA 证书
kubernetes 系统各组件需要使用 TLS 证书对通信进行加密,使用 CloudFlare 的 PKI 工具集生成自签名的 CA 证书,用来签名后续创建的其它 TLS 证书
根据认证对象可以将证书分成三类:服务器证书server cert,客户端证书client cert,对等证书peer cert(既是server cert又是client cert),在kubernetes 集群中需要的证书种类如下:
- etcd 节点需要标识自己服务的server cert,也需要client cert与etcd集群其他节点交互,当然可以分别指定2个证书,为方便这里使用一个对等证书
- master 节点需要标识 apiserver服务的server cert,也需要client cert连接etcd集群,这里也使用一个对等证书
- kubectl calico kube-proxy 只需要client cert,因此证书请求中 hosts 字段可以为空
- kubelet 需要标识自己服务的server cert,也需要client cert请求apiserver,也使用一个对等证书
整个集群要使用统一的CA 证书,只需要在ansible控制端创建,然后分发给其他节点;为了保证安装的幂等性,如果已经存在CA 证书,就跳过创建CA 步骤
创建 CA 配置文件 ca-config.json.j2
{
"signing": {
"default": {
"expiry": "{{ CERT_EXPIRY }}"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "{{ CERT_EXPIRY }}"
}
},
"profiles": {
"kcfg": {
"usages": [
"signing",
"key encipherment",
"client auth"
],
"expiry": "{{ CUSTOM_EXPIRY }}"
}
}
}
}
- signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;
- server auth:表示可以用该 CA 对 server 提供的证书进行验证;
- client auth:表示可以用该 CA 对 client 提供的证书进行验证;
- profile kubernetes 包含了server auth和client auth,所以可以签发三种不同类型证书; expiry 证书有效期,默认50年
- profile kcfg 在后面客户端kubeconfig证书管理中用到
创建 CA 证书签名请求 ca-csr.json.j2
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "HangZhou",
"L": "XS",
"O": "k8s",
"OU": "System"
}
],
"ca": {
"expiry": "876000h"
}
}
- ca expiry 指定ca证书的有效期,默认100年
生成CA 证书和私钥
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
生成 kubeconfig 配置文件
kubectl使用~/.kube/config 配置文件与kube-apiserver进行交互,且拥有管理 K8S集群的完全权限,
准备kubectl使用的admin 证书签名请求 admin-csr.json.j2
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "HangZhou",
"L": "XS",
"O": "system:masters",
"OU": "System"
}
]
}
- kubectl 使用客户端证书可以不指定hosts 字段
- 证书请求中 O 指定该证书的 Group 为 system:masters,而 RBAC 预定义的 ClusterRoleBinding 将 Group system:masters 与 ClusterRole cluster-admin 绑定,这就赋予了kubectl所有集群权限
$ kubectl describe clusterrolebinding cluster-admin
Name: cluster-admin
Labels: kubernetes.io/bootstrapping=rbac-defaults
Annotations: rbac.authorization.kubernetes.io/autoupdate=true
Role:
Kind: ClusterRole
Name: cluster-admin
Subjects:
Kind Name Namespace
---- ---- ---------
Group system:masters
生成 admin 用户证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
生成 ~/.kube/config 配置文件
使用kubectl config 生成kubeconfig 自动保存到 ~/.kube/config,生成后 cat ~/.kube/config可以验证配置文件包含 kube-apiserver 地址、证书、用户名等信息。
kubectl config set-cluster kubernetes --certificate-authority=ca.pem --embed-certs=true --server=127.0.0.1:8443
kubectl config set-credentials admin --client-certificate=admin.pem --embed-certs=true --client-key=admin-key.pem
kubectl config set-context kubernetes --cluster=kubernetes --user=admin
kubectl config use-context kubernetes
生成 kube-proxy.kubeconfig 配置文件
创建 kube-proxy 证书请求
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "HangZhou",
"L": "XS",
"O": "k8s",
"OU": "System"
}
]
}
- kube-proxy 使用客户端证书可以不指定hosts 字段
CN 指定该证书的 User 为 system:kube-proxy,预定义的 ClusterRoleBinding system:node-* proxier 将User system:kube-proxy 与 Role system:node-proxier 绑定,授予了调用 kube-apiserver Proxy 相关 API 的权限;
$ kubectl describe clusterrolebinding system:node-proxier
Name: system:node-proxier
Labels: kubernetes.io/bootstrapping=rbac-defaults
Annotations: rbac.authorization.kubernetes.io/autoupdate=true
Role:
Kind: ClusterRole
Name: system:node-proxier
Subjects:
Kind Name Namespace
---- ---- ---------
User system:kube-proxy
生成 system:kube-proxy 用户证书
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
生成 kube-proxy.kubeconfig
使用kubectl config 生成kubeconfig 自动保存到 kube-proxy.kubeconfig
kubectl config set-cluster kubernetes --certificate-authority=ca.pem --embed-certs=true --server=127.0.0.1:8443 --kubeconfig=kube-proxy.kubeconfig
kubectl config set-credentials kube-proxy --client-certificate=kube-proxy.pem --embed-certs=true --client-key=kube-proxy-key.pem --kubeconfig=kube-proxy.kubeconfig
kubectl config set-context default --cluster=kubernetes --user=kube-proxy --kubeconfig=kube-proxy.kubeconfig
kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
创建kube-controller-manager 和 kube-scheduler 组件的kubeconfig 文件
过程与创建kube-proxy.kubeconfig 类似,略。
prepare 角色
请在另外窗口打开roles/prepare/tasks/main.yml 文件,比较简单直观
- 设置基础操作系统软件和系统参数,请阅读脚本中的注释内容
- 创建一些基础文件目录、环境变量以及添加本地镜像仓库easzlab.io.local的域名解析
- 分发kubeconfig等配置文件
安装etcd集群
kuberntes 集群使用 etcd 存储所有数据,是最重要的组件之一,注意 etcd集群需要奇数个节点(1,3,5...),本文档使用3个节点做集群。
请在另外窗口打开roles/etcd/tasks/main.yml 文件,对照看以下讲解内容。
创建etcd证书
注意:证书是在部署节点创建好之后推送到目标etcd节点上去的,以增加ca证书的安全性
创建ectd证书请求 etcd-csr.json.j2
{
"CN": "etcd",
"hosts": [
{% for host in groups['etcd'] %}
"{{ host }}",
{% endfor %}
"127.0.0.1"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "HangZhou",
"L": "XS",
"O": "k8s",
"OU": "System"
}
]
}
etcd使用对等证书,hosts 字段必须指定授权使用该证书的 etcd 节点 IP,这里枚举了所有ectd节点的地址
创建etcd 服务文件 etcd.service.j2
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos
[Service]
Type=notify
WorkingDirectory={{ ETCD_DATA_DIR }}
ExecStart={{ bin_dir }}/etcd \
--name=etcd-{{ inventory_hostname }} \
--cert-file={{ ca_dir }}/etcd.pem \
--key-file={{ ca_dir }}/etcd-key.pem \
--peer-cert-file={{ ca_dir }}/etcd.pem \
--peer-key-file={{ ca_dir }}/etcd-key.pem \
--trusted-ca-file={{ ca_dir }}/ca.pem \
--peer-trusted-ca-file={{ ca_dir }}/ca.pem \
--initial-advertise-peer-urls=https://{{ inventory_hostname }}:2380 \
--listen-peer-urls=https://{{ inventory_hostname }}:2380 \
--listen-client-urls=https://{{ inventory_hostname }}:2379,http://127.0.0.1:2379 \
--advertise-client-urls=https://{{ inventory_hostname }}:2379 \
--initial-cluster-token=etcd-cluster-0 \
--initial-cluster={{ ETCD_NODES }} \
--initial-cluster-state={{ CLUSTER_STATE }} \
--data-dir={{ ETCD_DATA_DIR }} \
--wal-dir={{ ETCD_WAL_DIR }} \
--snapshot-count=50000 \
--auto-compaction-retention=1 \
--auto-compaction-mode=periodic \
--max-request-bytes=10485760 \
--quota-backend-bytes=8589934592
Restart=always
RestartSec=15
LimitNOFILE=65536
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
- 完整参数列表请使用 etcd --help 查询
- 注意etcd 即需要服务器证书也需要客户端证书,为方便使用一个peer 证书代替两个证书
- --initial-cluster-state 值为 new 时,--name 的参数值必须位于 --initial-cluster 列表中
- --snapshot-count --auto-compaction-retention 一些性能优化参数,请查阅etcd项目文档
- 设置--data-dir 和--wal-dir 使用不同磁盘目录,可以避免磁盘io竞争,提高性能,具体请参考etcd项目文档
验证etcd集群状态
- systemctl status etcd 查看服务状态
- journalctl -u etcd 查看运行日志
- 在任一 etcd 集群节点上执行如下命令
根据hosts中配置设置shell变量 $NODE_IPS
export NODE_IPS="192.168.1.1 192.168.1.2 192.168.1.3"
for ip in ${NODE_IPS}; do
ETCDCTL_API=3 etcdctl \
--endpoints=https://${ip}:2379 \
--cacert=/etc/kubernetes/ssl/ca.pem \
--cert=/etc/kubernetes/ssl/etcd.pem \
--key=/etc/kubernetes/ssl/etcd-key.pem \
endpoint health; done
预期结果:
https://192.168.1.1:2379 is healthy: successfully committed proposal: took = 2.210885ms
https://192.168.1.2:2379 is healthy: successfully committed proposal: took = 2.784043ms
https://192.168.1.3:2379 is healthy: successfully committed proposal: took = 3.275709ms
三台 etcd 的输出均为 healthy 时表示集群服务正常。
安装容器运行时
项目根据k8s版本提供不同的默认容器运行时:
- k8s 版本 < 1.24 时,支持docker containerd 可选
- k8s 版本 >= 1.24 时,仅支持 containerd
安装containerd
作为 CNCF 毕业项目,containerd 致力于提供简洁、可靠、可扩展的容器运行时;它被设计用来集成到 kubernetes 等系统使用,而不是像 docker 那样独立使用
- 安装指南 https://github.com/containerd/cri/blob/master/docs/installation.md
- 客户端 circtl 使用指南 https://github.com/containerd/cri/blob/master/docs/crictl.md
- man 文档 https://github.com/containerd/containerd/tree/master/docs/man
kubeasz 集成安装 containerd
- 注意:k8s 1.24以后,项目已经设置默认容器运行时为 containerd,无需手动修改
- 执行安装:分步安装ezctl setup xxxx 03,一键安装ezctl setup xxxx all
命令对比
安装kube_master节点
部署master节点主要包含三个组件apiserver scheduler controller-manager,其中:
- apiserver提供集群管理的REST API接口,包括认证授权、数据校验以及集群状态变更等
只有API Server才直接操作etcd
其他模块通过API Server查询或修改数据
提供其他模块之间的数据交互和通信的枢纽 - scheduler负责分配调度Pod到集群内的node节点
监听kube-apiserver,查询还未分配Node的Pod
根据调度策略为这些Pod分配节点 - controller-manager由一系列的控制器组成,它通过apiserver监控整个集群的状态,并确保集群处于预期的工作状态
高可用机制
- apiserver 无状态服务,可以通过外部负载均衡实现高可用,如项目采用的两种高可用架构:HA-1x (#584)和 HA-2x (#585)
- controller-manager 组件启动时会进行类似选举(leader);当多副本存在时,如果原先leader挂掉,那么会选举出新的leader,从而保证高可用;
- scheduler 类似选举机制
安装流程
cat playbooks/04.kube-master.yml
- hosts: kube_master
roles:
- kube-lb # 四层负载均衡,监听在127.0.0.1:6443,转发到真实master节点apiserver服务
- kube-master #
- kube-node # 因为网络、监控等daemonset组件,master节点也推荐安装kubelet和kube-proxy服务
...
创建 kubernetes 证书签名请求
{
"CN": "kubernetes",
"hosts": [
"127.0.0.1",
{% if groups['ex_lb']|length > 0 %}
"{{ hostvars[groups['ex_lb'][0]]['EX_APISERVER_VIP'] }}",
{% endif %}
{% for host in groups['kube_master'] %}
"{{ host }}",
{% endfor %}
"{{ CLUSTER_KUBERNETES_SVC_IP }}",
{% for host in MASTER_CERT_HOSTS %}
"{{ host }}",
{% endfor %}
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "HangZhou",
"L": "XS",
"O": "k8s",
"OU": "System"
}
]
}
kubernetes apiserver 使用对等证书,创建时hosts字段需要配置:
- 如果配置 ex_lb,需要把 EX_APISERVER_VIP 也配置进去
- 如果需要外部访问 apiserver,可选在config.yml配置 MASTER_CERT_HOSTS
- kubectl get svc 将看到集群中由api-server 创建的默认服务 kubernetes,因此也要把 kubernetes 服务名和各个服务域名也添加进去
创建apiserver的服务配置文件
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
ExecStart={{ bin_dir }}/kube-apiserver \
--allow-privileged=true \
--anonymous-auth=false \
--api-audiences=api,istio-ca \
--authorization-mode=Node,RBAC \
--bind-address={{ inventory_hostname }} \
--client-ca-file={{ ca_dir }}/ca.pem \
--endpoint-reconciler-type=lease \
--etcd-cafile={{ ca_dir }}/ca.pem \
--etcd-certfile={{ ca_dir }}/kubernetes.pem \
--etcd-keyfile={{ ca_dir }}/kubernetes-key.pem \
--etcd-servers={{ ETCD_ENDPOINTS }} \
--kubelet-certificate-authority={{ ca_dir }}/ca.pem \
--kubelet-client-certificate={{ ca_dir }}/kubernetes.pem \
--kubelet-client-key={{ ca_dir }}/kubernetes-key.pem \
--secure-port={{ SECURE_PORT }} \
--service-account-issuer=https://kubernetes.default.svc \
--service-account-signing-key-file={{ ca_dir }}/ca-key.pem \
--service-account-key-file={{ ca_dir }}/ca.pem \
--service-cluster-ip-range={{ SERVICE_CIDR }} \
--service-node-port-range={{ NODE_PORT_RANGE }} \
--tls-cert-file={{ ca_dir }}/kubernetes.pem \
--tls-private-key-file={{ ca_dir }}/kubernetes-key.pem \
--requestheader-client-ca-file={{ ca_dir }}/ca.pem \
--requestheader-allowed-names= \
--requestheader-extra-headers-prefix=X-Remote-Extra- \
--requestheader-group-headers=X-Remote-Group \
--requestheader-username-headers=X-Remote-User \
--proxy-client-cert-file={{ ca_dir }}/aggregator-proxy.pem \
--proxy-client-key-file={{ ca_dir }}/aggregator-proxy-key.pem \
--enable-aggregator-routing=true \
--v=2
Restart=always
RestartSec=5
Type=notify
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
- Kubernetes 对 API 访问需要依次经过认证、授权和准入控制(admission controll),认证解决用户是谁的问题,授权解决用户能做什么的问题,Admission Control则是资源管理方面的作用。
- 关于authorization-mode=Node,RBAC v1.7+支持Node授权,配合NodeRestriction准入控制来限制kubelet仅可访问node、endpoint、pod、service以及secret、configmap、PV和PVC等相关的资源;需要注意的是v1.7中Node 授权是默认开启的,v1.8中需要显式配置开启,否则 Node无法正常工作
- 详细参数配置请参考kube-apiserver --help,关于认证、授权和准入控制请阅读
- 增加了访问kubelet使用的证书配置,防止匿名访问kubelet的安全漏洞,详见漏洞说明
创建controller-manager 的服务文件
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
ExecStart={{ bin_dir }}/kube-controller-manager \
--allocate-node-cidrs=true \
--authentication-kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \
--authorization-kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \
--bind-address=0.0.0.0 \
--cluster-cidr={{ CLUSTER_CIDR }} \
--cluster-name=kubernetes \
--cluster-signing-cert-file={{ ca_dir }}/ca.pem \
--cluster-signing-key-file={{ ca_dir }}/ca-key.pem \
--kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \
--leader-elect=true \
--node-cidr-mask-size={{ NODE_CIDR_LEN }} \
--root-ca-file={{ ca_dir }}/ca.pem \
--service-account-private-key-file={{ ca_dir }}/ca-key.pem \
--service-cluster-ip-range={{ SERVICE_CIDR }} \
--use-service-account-credentials=true \
--v=2
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
- --cluster-cidr 指定 Cluster 中 Pod 的 CIDR 范围,该网段在各 Node 间必须路由可达(flannel/calico 等网络插件实现)
- --service-cluster-ip-range 参数指定 Cluster 中 Service 的CIDR范围,必须和 kube-apiserver 中的参数一致
- --cluster-signing-* 指定的证书和私钥文件用来签名为 TLS BootStrap 创建的证书和私钥
- --root-ca-file 用来对 kube-apiserver 证书进行校验,指定该参数后,才会在Pod 容器的 ServiceAccount 中放置该 CA 证书文件
- --leader-elect=true 使用多节点选主的方式选择主节点。只有主节点才会启动所有控制器,而其他从节点则仅执行选主算法
创建scheduler 的服务文件
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
ExecStart={{ bin_dir }}/kube-scheduler \
--authentication-kubeconfig=/etc/kubernetes/kube-scheduler.kubeconfig \
--authorization-kubeconfig=/etc/kubernetes/kube-scheduler.kubeconfig \
--bind-address=0.0.0.0 \
--kubeconfig=/etc/kubernetes/kube-scheduler.kubeconfig \
--leader-elect=true \
--v=2
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
- --leader-elect=true 部署多台机器组成的 master 集群时选举产生一个处于工作状态的 kube-controller-manager 进程
在master 节点安装 node 服务: kubelet kube-proxy
项目master 分支使用 DaemonSet 方式安装网络插件,如果master 节点不安装 kubelet 服务是无法安装网络插件的,如果 master 节点不安装网络插件,那么通过apiserver 方式无法访问 dashboard kibana等管理界面,ISSUES #130
# vi 04.kube-master.yml
- hosts: kube_master
roles:
- kube_master
- kube_node
# 禁止业务 pod调度到 master节点
tasks:
- name: 禁止业务 pod调度到 master节点
shell: "{{ bin_dir }}/kubectl cordon {{ inventory_hostname }} "
when: DEPLOY_MODE != "allinone"
ignore_errors: true
在master 节点也同时成为 node 节点后,默认业务 POD也会调度到 master节点,多主模式下这显然增加了 master节点的负载,因此可以使用 kubectl cordon命令禁止业务 POD调度到 master节点
master 集群的验证
运行 ansible-playbook 04.kube-master.yml 成功后,验证 master节点的主要组件:
# 查看进程状态
systemctl status kube-apiserver
systemctl status kube-controller-manager
systemctl status kube-scheduler
# 查看进程运行日志
journalctl -u kube-apiserver
journalctl -u kube-controller-manager
journalctl -u kube-scheduler
执行 kubectl get componentstatus 可以看到
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {"health": "true"}
etcd-2 Healthy {"health": "true"}
etcd-1 Healthy {"health": "true"}
安装kube_node节点
kube_node 是集群中运行工作负载的节点,前置条件需要先部署好kube_master节点,它需要部署如下组件
cat playbooks/05.kube-node.yml
- hosts: kube_node
roles:
- { role: kube-lb, when: "inventory_hostname not in groups['kube_master']" }
- { role: kube-node, when: "inventory_hostname not in groups['kube_master']" }
- kube-lb:由nginx裁剪编译的四层负载均衡,用于将请求转发到主节点的 apiserver服务
- kubelet:kube_node上最主要的组件
- kube-proxy: 发布应用服务与负载均衡
创建cni 基础网络插件配置文件
因为后续需要用 DaemonSet Pod方式运行k8s网络插件,所以kubelet.server服务必须开启cni相关参数,并且提供cni网络配置文件
创建 kubelet 的服务文件
- 根据官方建议独立使用 kubelet 配置文件,详见roles/kube-node/templates/kubelet-config.yaml.j2
- 必须先创建工作目录 /var/lib/kubelet
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
[Service]
WorkingDirectory=/var/lib/kubelet
{% if ansible_distribution == "Debian" and ansible_distribution_version|int >= 10 %}
ExecStartPre=/bin/mount -o remount,rw '/sys/fs/cgroup'
{% endif %}
{% if KUBE_RESERVED_ENABLED == "yes" or SYS_RESERVED_ENABLED == "yes" %}
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpu/podruntime.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpuacct/podruntime.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpuset/podruntime.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/memory/podruntime.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/pids/podruntime.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/systemd/podruntime.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpu/system.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpuacct/system.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/cpuset/system.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/memory/system.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/pids/system.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/systemd/system.slice
{% if ansible_distribution != "Debian" %}
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/hugetlb/podruntime.slice
ExecStartPre=/bin/mkdir -p /sys/fs/cgroup/hugetlb/system.slice
{% endif %}
{% endif %}
ExecStart={{ bin_dir }}/kubelet \
--config=/var/lib/kubelet/config.yaml \
--container-runtime-endpoint=unix:///run/containerd/containerd.sock \
--hostname-override={{ inventory_hostname }} \
--kubeconfig=/etc/kubernetes/kubelet.kubeconfig \
--root-dir={{ KUBELET_ROOT_DIR }} \
--v=2
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
- --ExecStartPre=/bin/mkdir -p xxx 对于某些系统(centos7)cpuset和hugetlb 是默认没有初始化system.slice 的,需要手动创建,否则在启用--kube-reserved-cgroup 时会报错Failed to start ContainerManager Failed to enforce System Reserved Cgroup Limits
- 关于kubelet资源预留相关配置请参考 https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/
创建 kube-proxy kubeconfig 文件
该步骤已经在 deploy节点完成,roles/deploy/tasks/main.yml
- 生成的kube-proxy.kubeconfig 配置文件需要移动到/etc/kubernetes/目录,后续kube-proxy服务启动参数里面需要指定
创建 kube-proxy服务文件
[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
WorkingDirectory=/var/lib/kube-proxy
ExecStart={{ bin_dir }}/kube-proxy \
--config=/var/lib/kube-proxy/kube-proxy-config.yaml
Restart=always
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
验证 node 状态
systemctl status kubelet # 查看状态
systemctl status kube-proxy
journalctl -u kubelet # 查看日志
journalctl -u kube-proxy
运行 kubectl get node 可以看到类似
NAME STATUS ROLES AGE VERSION
192.168.1.42 Ready 2d v1.9.0
192.168.1.43 Ready 2d v1.9.0
192.168.1.44 Ready 2d v1.9.0
安装网络组件
首先回顾下K8S网络设计原则,在配置集群网络插件或者实践K8S 应用/服务部署请牢记这些原则:
- 1.每个Pod都拥有一个独立IP地址,Pod内所有容器共享一个网络命名空间
- 2.集群内所有Pod都在一个直接连通的扁平网络中,可通过IP直接访问
- 所有容器之间无需NAT就可以直接互相访问
- 所有Node和所有容器之间无需NAT就可以直接互相访问
- 容器自己看到的IP跟其他容器看到的一样
- 3.Service cluster IP只可在集群内部访问,外部请求需要通过NodePort、LoadBalance或者Ingress来访问
Container Network Interface (CNI)是目前CNCF主推的网络模型,它由两部分组成
- CNI Plugin负责给容器配置网络,它包括两个基本的接口
- 配置网络: AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
- 清理网络: DelNetwork(net *NetworkConfig, rt *RuntimeConf) error
- IPAM Plugin负责给容器分配IP地址
Kubernetes Pod的网络是这样创建的:
- 每个Pod除了创建时指定的容器外,都有一个kubelet启动时指定的基础容器,即pause容器
- kubelet创建基础容器生成network namespace
- kubelet调用网络CNI driver,由它根据配置调用具体的CNI 插件
- CNI 插件给基础容器配置网络
- Pod 中其他的容器共享使用基础容器的网络
本项目基于CNI driver 调用各种网络插件来配置kubernetes的网络,常用CNI插件有 flannel calico cilium等等,这些插件各有优势,也在互相借鉴学习优点,比如:在所有node节点都在一个二层网络时候,flannel提供hostgw实现,避免vxlan实现的udp封装开销,估计是目前最高效的;calico也针对L3 Fabric,推出了IPinIP的选项,利用了GRE隧道封装;因此这些插件都能适合很多实际应用场景。
项目当前内置支持的网络插件有:calico cilium flannel kube-ovn kube-router
安装讲解
- 安装calico https://github.com/easzlab/kubeasz/blob/master/docs/setup/network-plugin/calico.md
- 安装cilium https://github.com/easzlab/kubeasz/blob/master/docs/setup/network-plugin/cilium.md
- 安装flannel https://github.com/easzlab/kubeasz/blob/master/docs/setup/network-plugin/flannel.md
- 安装kube-ovn 暂未更新
- 安装kube-router 暂未更新
安装集群主要插件
目前挑选一些常用、必要的插件自动集成到安装脚本之中:
- coredns https://github.com/easzlab/kubeasz/blob/master/docs/guide/kubedns.md
- nodelocaldns https://github.com/easzlab/kubeasz/blob/master/docs/guide/kubedns.md
- metrics-server https://github.com/easzlab/kubeasz/blob/master/docs/guide/metrics-server.md
- dashboard https://github.com/easzlab/kubeasz/blob/master/docs/guide/dashboard.md
集群可选安装
- prometheus https://github.com/easzlab/kubeasz/blob/master/docs/guide/prometheus.md
- network_check https://github.com/easzlab/kubeasz/blob/master/docs/setup/network-plugin/network-check.md
- nfs_provisioner https://github.com/easzlab/kubeasz/tree/master/docs/setup
kubeasz 默认不安装上述插件,可以在配置文件(clusters/xxx/config.yml)中开启,支持离线方式安装(./ezdown -X 会额外下载这些组件镜像,并推送到本地镜像仓库easzlab.io.local:5000)
kubeasz 默认安装上述基础插件,并支持离线方式安装(./ezdown -D 命令会自动下载组件镜像,并推送到本地镜像仓库easzlab.io.local:5000)
安装脚本
详见roles/cluster-addon/ 目录
- 1.根据hosts文件中配置的CLUSTER_DNS_SVC_IP CLUSTER_DNS_DOMAIN等参数生成kubedns.yaml和coredns.yaml文件
- 2.注册变量pod_info,pod_info用来判断现有集群是否已经运行各种插件
- 3.根据pod_info和配置开关逐个进行/跳过插件安装