k8s kubeasz安装k8s集群

目录
  • 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

集群规划和基础参数设定

机器准备

k8s kubeasz安装k8s集群_第1张图片

机器配置:

  • 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
    命令对比

k8s kubeasz安装k8s集群_第2张图片

image

安装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和配置开关逐个进行/跳过插件安装

你可能感兴趣的:(kubernetes,docker,容器,云原生,java)