Kubernetes v1.19.16 二进制高可用部署

文章更新于:2023年5月4日

1. 此文适合于有一定Linux基础的同学阅读;
2. 基于 centos 7.x 完成,其他Linux操作系统,请自行调整;
3. 阿里云平台,不能使用keepalive来实现高可用,请使用阿里云上内网LBS或虚拟IP(VIP)来实现,请搜索相关文章

一、基础环境

服务器环境

5台 CentOS7.x 虚拟机,在MacOS下使用 Parallels Desktop 完成创建

192.168.0.150    # master节点 2C4
192.168.0.151    # master节点 2C4
192.168.0.152    # master节点 2C4
192.168.0.153    # 工作节点 2C4
192.168.0.154    # 工作节点 2C4

注意

生产环境时,master节点建议使用4C8的配置

软件及版本

  • kubernetes 1.19.16
  • etcd 3.4.18
  • calico 3.16.0
  • cfssl 1.2.0 (证书工具)
  • keepalive (虚拟IP)
  • haproxy (高可用)
  • coredns 1.7.0 (docker image)
  • pause 3.2 (docker image)

约定值


# kubernetes服务的ip网段
10.255.0.0/16

# k8s的api-server的服务ip
10.255.0.1

# dns服务的ip地址
10.255.0.2

# pod网段
172.23.0.0/16

# 虚拟IP (VIP)
192.168.0.160


# VIP代理后的IP及端口
192.168.0.160:8443

# node port range
30000-32767

系统设置(所有机器)

1、设置hostname,后面会使用hostname进行通信:

# 可分别设置每台机器的hostname
$ hostnamectl set-hostname master1

配置hosts

$ vi /etc/hosts

192.168.0.150    master1
192.168.0.151    master2
192.168.0.152    master3
192.168.0.153    node1
192.168.0.154    node2
192.168.0.160    vip

2、安装一些基础软件

# 更新yum
$ yum update -y 

# 安装一些包
$ yum install -y conntrack ipvsadm ipset jq sysstat curl wget iptables libseccomp

3、系统设置


# 关闭防火墙
$ systemctl stop firewalld && systemctl disable firewalld


# 关闭swap-交换分区
$ swapoff -a
$ sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab

# 关闭selinux
$ setenforce 0
$ sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

4、修改网络


$ vi /etc/sysctl.d/k8s.conf 

net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
vm.swappiness=0
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100


$ sysctl -p /etc/sysctl.d/k8s.conf

5、安装和配置docker ce

安装可自行查询资料

# 启动docker

$ systemctl enable docker && systemctl start docker


# 查看docker是否运行成功

$ systemctl status docker


二、准备二进制文件(所有机器)

2.1 配置免密登录

可以快速从一台机器上复制证书、配置文件、二进制等文件到其他机器

在master1上,操作:


$ ssh-keygen -t rsa

Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:AHglkRC/dxJ9FtgPqx+F4ULxMucVVnFycT04yj5D//w root@master1
The key's randomart image is:
+---[RSA 2048]----+
|  o+++. .+. o.=o*|
|  ..oo .o.+o + =o|
|   .. o.+.**o . .|
|     . o.B+=o    |
|    . o So+..    |
|     . o. .+ .   |
|         . .o o  |
|          .    o |
|                E|
+----[SHA256]-----+

查看公钥内容:

$ cat ~/.ssh/id_rsa.pub

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3d+t/3iv0a2Yh+26afvvUYX6LNad/WRDOMqgkvynUkF5ehQ/rykaGBzglJjbYL11B3lZrKip14CYxaKfdXoK2K2sJ61V7VK+j4GOADStfMdvmoEkR+GQwzZk6ra0hN5LuSpyi1o1g6lqy/KppeHqoZk6hj23Ce7DDsPgmZgn79z2iTjvWA5TyiVtIiRL+BCC8kDTM3ODZS5MXxjYRvwQvlv/Ip8i7Xua0a6hJwspgIlJ7LIouEr+osAwkFeXQW/AJCVawKqUcPVRPXFe6NDRFD1duwl9Ofb+1z/s4R5sOqXkglNqR1v9j5ha/vzE0NaTuSBVIQXFavW9NgFPPIboJ root@master1

id_rsa.pub 中的内容copy所有机器的ssh授权文件中,包括master1

# 如果.ssh目录不存在,先创建: mkdir ~/.ssh
$ echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3d+t/3iv0a2Yh+26afvvUYX6LNad/WRDOMqgkvynUkF5ehQ/rykaGBzglJjbYL11B3lZrKip14CYxaKfdXoK2K2sJ61V7VK+j4GOADStfMdvmoEkR+GQwzZk6ra0hN5LuSpyi1o1g6lqy/KppeHqoZk6hj23Ce7DDsPgmZgn79z2iTjvWA5TyiVtIiRL+BCC8kDTM3ODZS5MXxjYRvwQvlv/Ip8i7Xua0a6hJwspgIlJ7LIouEr+osAwkFeXQW/AJCVawKqUcPVRPXFe6NDRFD1duwl9Ofb+1z/s4R5sOqXkglNqR1v9j5ha/vzE0NaTuSBVIQXFavW9NgFPPIboJ root@master1" >> ~/.ssh/authorized_keys

测试免密登录是否成功,不需要密码,说明设置成功。

[root@master1 ~]# ssh node1
Last login: Fri Nov  5 04:04:08 2021 from master1
[root@node1 ~]#

2.2 下载二进制文件

只在master1上操作,然后通过从master1批量copy到其他机器

下载和整理k8s文件

下载并解压

[root@master1 ~]# cd /usr/local/src
[root@master1 src]# wget https://dl.k8s.io/v1.19.16/kubernetes-server-linux-amd64.tar.gz
[root@master1 src]# tar -zxvf kubernetes-server-linux-amd64.tar.gz

文件存放在 kubernetes/server/bin下:

[root@master1 bin]# ll
total 946884
-rwxr-xr-x 1 root root  46776320 Oct 27 12:34 apiextensions-apiserver
-rwxr-xr-x 1 root root  39063552 Oct 27 12:34 kubeadm
-rwxr-xr-x 1 root root  43872256 Oct 27 12:34 kube-aggregator
-rwxr-xr-x 1 root root 115347456 Oct 27 12:34 kube-apiserver
-rw-r--r-- 1 root root         9 Oct 27 12:33 kube-apiserver.docker_tag
-rw------- 1 root root 120163840 Oct 27 12:33 kube-apiserver.tar
-rwxr-xr-x 1 root root 107319296 Oct 27 12:34 kube-controller-manager
-rw-r--r-- 1 root root         9 Oct 27 12:33 kube-controller-manager.docker_tag
-rw------- 1 root root 112135680 Oct 27 12:33 kube-controller-manager.tar
-rwxr-xr-x 1 root root  42950656 Oct 27 12:34 kubectl
-rwxr-xr-x 1 root root 110113992 Oct 27 12:34 kubelet
-rwxr-xr-x 1 root root  38756352 Oct 27 12:34 kube-proxy
-rw-r--r-- 1 root root         9 Oct 27 12:33 kube-proxy.docker_tag
-rw------- 1 root root 100759040 Oct 27 12:33 kube-proxy.tar
-rwxr-xr-x 1 root root  42938368 Oct 27 12:34 kube-scheduler
-rw-r--r-- 1 root root         9 Oct 27 12:33 kube-scheduler.docker_tag
-rw------- 1 root root  47754752 Oct 27 12:33 kube-scheduler.tar
-rwxr-xr-x 1 root root   1634304 Oct 27 12:34 mounter

整理文件,把不同节点需要的文件,放在不同的目录:

# 创建两个目录
$ [root@master1 bin]# mkdir -p /usr/local/src/k8s-master
$ [root@master1 bin]# mkdir -p /usr/local/src/k8s-worker

# 分别复制文件到两个目录
$ [root@master1 bin]# for i in kubeadm kube-apiserver kube-controller-manager kubectl kube-scheduler;do cp $i /usr/local/src/k8s-master/; done
$ [root@master1 bin]# for i in kubelet kube-proxy;do cp $i /usr/local/src/k8s-worker/; done

下载和整理etcd文件

下载并解压

$ cd /usr/local/src

[root@master1 src]# wget https://github.com/etcd-io/etcd/releases/download/v3.4.18/etcd-v3.4.18-linux-amd64.tar
[root@master1 src]# tar -zxvf etcd-v3.4.18-linux-amd64.tar

复制etcd相关文件到 k8s-master目录:


[root@master1 src]# cd etcd-v3.4.18-linux-amd64
[root@master1 etcd-v3.4.18-linux-amd64]# cp etcd* /usr/local/src/k8s-master/

查看 k8s-master中的文件

[root@master1 src]# ls k8s-master/
etcd  etcdctl  kubeadm  kube-apiserver  kube-controller-manager  kubectl  kube-scheduler

2.3 分发二进制文件到其他机器

分别在所有机器上,创建目录 /opt/kubernetes/bin

$ mkdir -p /opt/kubernetes/bin

分发到master节点

[root@master1 ~]# for i in master1 master2 master3; do scp /usr/local/src/k8s-master/* $i:/opt/kubernetes/bin/; done

分发到worker节点

[root@master1 ~]# for i in node1 node2; do scp /usr/local/src/k8s-worker/* $i:/opt/kubernetes/bin/; done

给所有节点设置 PATH 环境变量

[root@master1 ~]# for i in master1 master2 master3 node1 node2; do ssh $i "echo 'PATH=/opt/kubernetes/bin:$PATH' >> ~/.bashrc"; done

分别在每台机器上执行环境变量可用

$ source ~/.bashrc


三、集群部署

3.1 安装cfssl证书工具

在master1上下载cfssl

root@master1 bin]# wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O ~/bin/cfssl
[root@master1 bin]# wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O ~/bin/cfssljson

给运行权限

[root@master1 bin]# chmod +x cfssl
[root@master1 bin]# chmod +x cfssljson

设置 ~/bin 的环境变量

[root@master1 bin]# vi ~/.bashrc

PATH=~/bin:$PATH

# 生效
[root@master1 bin]# source ~/.bashrc

3.2 生成 kubernetes 所需的根证书

[root@master1 bin]# vi ca-csr.json

{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "SICHUAN",
      "L": "CHENGDU",
      "O": "k8s",
      "OU": "system"
    }
  ]
}

生成证书和私钥

[root@master1 ~]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca

2021/11/08 02:42:32 [INFO] generating a new CA key and certificate from CSR
2021/11/08 02:42:32 [INFO] generate received request
2021/11/08 02:42:32 [INFO] received CSR
2021/11/08 02:42:32 [INFO] generating key: rsa-2048
2021/11/08 02:42:32 [INFO] encoded CSR
2021/11/08 02:42:32 [INFO] signed certificate with serial number 627140244887982433551543860823384941108151783458

生成 ca-key.pemca.pem,一个私钥,一个证书

[root@master1 ~]# ll -h
total 20K
-rw-------. 1 root root 1.3K Nov  5 03:40 anaconda-ks.cfg
drwxr-xr-x  2 root root   36 Nov  8 02:35 bin
-rw-r--r--  1 root root 1001 Nov  8 02:42 ca.csr
-rw-r--r--  1 root root  208 Nov  8 02:42 ca-csr.json
-rw-------  1 root root 1.7K Nov  8 02:42 ca-key.pem
-rw-r--r--  1 root root 1.4K Nov  8 02:42 ca.pem

将这两个文件传输到每个 master节点上

#在3个master节点,创建 /etc/kubernetes/pki 目录
[root@master1 ~]# for i in master1 master2 master3; do ssh $i "mkdir -p /etc/kubernetes/pki/"; done

#复制两述两个文件到 三个master节点的 /etc/kubernetes/pki 目录下
[root@master1 ~]# for i in master1 master2 master3; do scp *.pem $i:/etc/kubernetes/pki/; done


3.3 在master节点部署etcd集群

3.3.1 生成etcd所需的私钥和证书

[root@master1 ~]#  vi ca-config.json

{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "87600h"
      }
    }
  }
}
[root@master1 ~]#  vi etcd-csr.json

{
  "CN": "etcd",
  "hosts": [
    "127.0.0.1",
    "192.168.0.150",
    "192.168.0.151",
    "192.168.0.152"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "SICHUAN",
      "L": "CHENGDU",
      "O": "k8s",
      "OU": "system"
    }
  ]
}

生成文件

[root@master1 ~]# cfssl gencert -ca=ca.pem \
     -ca-key=ca-key.pem \
     -config=ca-config.json \
     -profile=kubernetes etcd-csr.json | cfssljson -bare etcd

检查文件:

[root@master1 ~]# ls etcd*.pem

etcd-key.pem  etcd.pem

无问题后同步到所有 master节点

[root@master1 ~]# for i in master1 master2 master3; do scp etcd*.pem $i:/etc/kubernetes/pki/; done

3.3.2 创建etcd的systemd服务文件

[root@master1 ~]# vi etcd.service

[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos

[Service]
Type=notify
WorkingDirectory=/var/lib/etcd/
ExecStart=/opt/kubernetes/bin/etcd \
  --data-dir=/var/lib/etcd \
  --name=master1 \
  --cert-file=/etc/kubernetes/pki/etcd.pem \
  --key-file=/etc/kubernetes/pki/etcd-key.pem \
  --trusted-ca-file=/etc/kubernetes/pki/ca.pem \
  --peer-cert-file=/etc/kubernetes/pki/etcd.pem \
  --peer-key-file=/etc/kubernetes/pki/etcd-key.pem \
  --peer-trusted-ca-file=/etc/kubernetes/pki/ca.pem \
  --peer-client-cert-auth \
  --client-cert-auth \
  --listen-peer-urls=https://192.168.0.150:2380 \
  --initial-advertise-peer-urls=https://192.168.0.150:2380 \
  --listen-client-urls=https://192.168.0.150:2379,http://127.0.0.1:2379 \
  --advertise-client-urls=https://192.168.0.150:2379 \
  --initial-cluster-token=etcd-cluster-0 \
  --initial-cluster=master1=https://192.168.0.150:2380,master2=https://192.168.0.151:2380,master3=https://192.168.0.152:2380 \
  --initial-cluster-state=new
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

etcd.service同步到每个master节点

[root@master1 ~]# for i in master1 master2 master3; do scp etcd.service $i:/etc/systemd/system/; done

修改 master1之外的其他站点IP及名称:

  # 修改成所处节点的hostname
  --name=master1 \

  # 修改为所处节点的IP(内网)
  --listen-peer-urls=https://192.168.0.150:2380 \
  --initial-advertise-peer-urls=https://192.168.0.150:2380 \
  --listen-client-urls=https://192.168.0.150:2379,http://127.0.0.1:2379 \
  --advertise-client-urls=https://192.168.0.150:2379 \

为每个 master节点上创建 etcd的工作目录 /var/lib/etcd

[root@master1 ~]# for i in master1 master2 master3; do ssh $i "mkdir -p /var/lib/etcd"; done

3.3.3 启动服务

分别在 master1 master2 master3,启动etcd:

$ systemctl daemon-reload && systemctl enable etcd && systemctl restart etcd

查看是否启动后的状态

$ systemctl status etcd

如果启动失败,查看日志

$ journalctl -f -u etcd


3.4 在master节点部署 kube-apiserver

3.4.1 生成所需的私钥和证书

新建配置文件

[root@master1 ~]# vi kubernetes-csr.json


{
  "CN": "kubernetes",
  "hosts": [
    "127.0.0.1",
    "192.168.0.150",
    "192.168.0.151",
    "192.168.0.152",
    "192.168.0.160",
    "10.255.0.1",
    "kubernetes",
    "kubernetes.default",
    "kubernetes.default.svc",
    "kubernetes.default.svc.cluster",
    "kubernetes.default.svc.cluster.local"
  ],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "SICHUAN",
      "L": "CHENGDU",
      "O": "k8s",
      "OU": "system"
    }
  ]
}

生成私钥和证书

[root@master1 ~]# cfssl gencert -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes

分发到每个master节点

[root@master1 ~]#  for i in master1 master2 master3; do scp kubernetes*.pem $i:/etc/kubernetes/pki/; done

3.4.2 创建kube-apiserver的systemd服务文件

创建文件

[root@master1 ~]# vi kube-apiserver.service

[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target

[Service]
ExecStart=/opt/kubernetes/bin/kube-apiserver \
  --enable-admission-plugins=NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \
  --anonymous-auth=false \
  --advertise-address=192.168.0.150 \
  --bind-address=0.0.0.0 \
  --insecure-port=0 \
  --authorization-mode=Node,RBAC \
  --runtime-config=api/all=true \
  --enable-bootstrap-token-auth \
  --service-cluster-ip-range=10.255.0.0/16 \
  --service-node-port-range=30000-32767 \
  --tls-cert-file=/etc/kubernetes/pki/kubernetes.pem \
  --tls-private-key-file=/etc/kubernetes/pki/kubernetes-key.pem \
  --client-ca-file=/etc/kubernetes/pki/ca.pem \
  --kubelet-client-certificate=/etc/kubernetes/pki/kubernetes.pem \
  --kubelet-client-key=/etc/kubernetes/pki/kubernetes-key.pem \
  --service-account-key-file=/etc/kubernetes/pki/ca-key.pem \
  --etcd-cafile=/etc/kubernetes/pki/ca.pem \
  --etcd-certfile=/etc/kubernetes/pki/kubernetes.pem \
  --etcd-keyfile=/etc/kubernetes/pki/kubernetes-key.pem \
  --etcd-servers=https://192.168.0.150:2379,https://192.168.0.151:2379,https://192.168.0.152:2379 \
  --enable-swagger-ui=true \
  --allow-privileged=true \
  --apiserver-count=3 \
  --audit-log-maxage=30 \
  --audit-log-maxbackup=3 \
  --audit-log-maxsize=100 \
  --audit-log-path=/var/log/kube-apiserver-audit.log \
  --event-ttl=1h \
  --alsologtostderr=true \
  --logtostderr=false \
  --log-dir=/var/log/kubernetes \
  --v=2
Restart=on-failure
RestartSec=5
Type=notify
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

分发到每个master节点

[root@master1 ~]# for i in master1 master2 master3; do scp kube-apiserver.service $i:/etc/systemd/system/; done

修改除 master1机器之外的 kube-apiserver.service配置

  # 修改为节点所在的内网IP
  --advertise-address=192.168.0.150

在所有master节点,创建 api-server的日志目录

[root@master1 ~]# for i in master1 master2 master3; do ssh $i "mkdir -p /var/log/kubernetes"; done

3.4.3 启动服务

在每个 master节点上启动kube-apiserver服务

$ systemctl daemon-reload && systemctl enable kube-apiserver && systemctl restart kube-apiserver

查看状态:

$ systemctl status kube-apiserver

如果启动失败,排查问题

$ journalctl -f -u kube-apiserver


3.5 安装 keepalived

在所有的master 节点安装,用于实现虚拟IP

[root@master1 ~]# yum install -y keepalived

[root@master1 ~]# vi /etc/keepalived/keepalived.conf

global_defs { # 全局配置
   notification_email { # 通知邮件,可以多个
        301109640@qq.com
   }
   notification_email_from Alexandre.Cassen@firewall.loc # 通知邮件发件人,可以自行修改
   smtp_server 127.0.0.1     # 邮件服务器地址
   smtp_connect_timeout 30   # 邮件服务器连接的timeout
   router_id LVS_1              # 机器标识,可以不修改,多台机器可相同
}

vrrp_instance VI_1 {  # vroute标识
    state MASTER      # 当前节点的状态:主节点       
    interface eth0    # 发送vip通告的接口
    lvs_sync_daemon_inteface eth0
    virtual_router_id 79 # 虚拟路由的ID号是虚拟路由MAC的最后一位地址
    advert_int 1         # vip通告的时间间隔   
    priority 100          # 此节点的优先级主节点的优先级需要比其他节点高,我配置成:master1 100 master2 80 master3 70   
    authentication {      # 认证配置
        auth_type PASS # 认证机制默认是明文
        auth_pass 1111 # 随机字符当密码,要和虚拟路由器中其它路由器保持一致
    }
    virtual_ipaddress { # vip
      192.168.0.160/20  # 192.168.0.160 的vip
    }
}

启动

[root@master1 ~]# systemctl enable keepalived && systemctl restart keepalived

启动成功后,可以看到类似信息:

[root@master1 ~]# ip addr

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:1c:42:3f:7b:c5 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.150/24 brd 192.168.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet 192.168.0.160/20 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::d541:71b6:7b10:71cb/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

如果 master1不可用时,VIP可能漂移到 master2master3上

3.6 安装和配置haproxy

在所有master节点安装haproxy,用于实现tcp层的kube-apiserver代理

$ yum install -y haproxy

修改配置

$ vi /etc/haproxy/haproxy.cfg


global
        chroot  /var/lib/haproxy
        daemon
        group haproxy
        user haproxy
        log 127.0.0.1:514 local0 warning
        pidfile /var/lib/haproxy.pid
        maxconn 20000
        spread-checks 3
        nbproc 8

defaults
        log     global
        mode    tcp
        retries 3
        option redispatch

listen https-apiserver
        bind 0.0.0.0:8443 # 此处为8443
        mode tcp
        balance roundrobin
        timeout server 900s
        timeout connect 15s

        server master1 192.168.0.150:6443 check port 6443 inter 5000 fall 5
        server master2 192.168.0.151:6443 check port 6443 inter 5000 fall 5
        server master3 192.168.0.152:6443 check port 6443 inter 5000 fall 5

启动haproxy

$ systemctl enable haproxy && systemctl restart haproxy

检测代理后的kube-apiserver地址及端口

$ curl --insecure https://192.168.0.160:8443/


{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {

  },
  "status": "Failure",
  "message": "Unauthorized",
  "reason": "Unauthorized",
  "code": 401
}


3.7 安装kubectl

可以在任意节点安装。kubectl是集群的命令行管理工具

3.7.1 创建所需的私钥和证书

[root@master1 ~]# vi admin-csr.json

{
  "CN": "admin",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "SICHUAN",
      "L": "CHENGDU",
      "O": "system:masters",
      "OU": "system"
    }
  ]
}

生成私钥和证书

[root@master1 ~]# cfssl gencert -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -profile=kubernetes admin-csr.json | cfssljson -bare admin

3.7.2 创建kubeconfig配置文件

设置集群参数


[root@master1 ~]# kubectl config set-cluster kubernetes \
  --certificate-authority=ca.pem \
  --embed-certs=true \
  --server=https://192.168.0.160:8443 \
  --kubeconfig=kube.config

设置客户端认证参数

[root@master1 ~]# kubectl config set-credentials admin \
  --client-certificate=admin.pem \
  --client-key=admin-key.pem \
  --embed-certs=true \
  --kubeconfig=kube.config

设置下下文参数

[root@master1 ~]# kubectl config set-context kubernetes \
  --cluster=kubernetes \
  --user=admin \
  --kubeconfig=kube.config

设置默认上下文

[root@master1 ~]# kubectl config use-context kubernetes --kubeconfig=kube.config

复制文件到 .kube目录下,如果没有.kube目录,使用 mkdir -p ~/.kube 创建

[root@master1 ~]# cp kube.config ~/.kube/config

3.7.3 授权 kubernetes访问 kubelet API的权限


[root@master1 ~]# kubectl create clusterrolebinding kube-apiserver:kubelet-apis --clusterrole=system:kubelet-api-admin --user kubernetes

clusterrolebinding.rbac.authorization.k8s.io/kube-apiserver:kubelet-apis created

3.7.4 测试kubectl可用

查看集群信息

[root@master1 ~]# kubectl cluster-info

Kubernetes master is running at https://192.168.0.160:8443

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

查看所有资源

[root@master1 ~]# kubectl get all --all-namespaces -o wide

NAMESPACE   NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE     SELECTOR
default     service/kubernetes   ClusterIP   10.255.0.1   <none>        443/TCP   4h57m   <none>

查看集群中的所有组件状态

[root@master1 ~]# kubectl get cs
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME                 STATUS      MESSAGE                                                                                       ERROR
scheduler            Unhealthy   Get "http://127.0.0.1:10251/healthz": dial tcp 127.0.0.1:10251: connect: connection refused
controller-manager   Unhealthy   Get "http://127.0.0.1:10252/healthz": dial tcp 127.0.0.1:10252: connect: connection refused
etcd-0               Healthy     {"health":"true"}
etcd-1               Healthy     {"health":"true"}
etcd-2               Healthy     {"health":"true"}


3.8 部署 kube-controller-manager

在所有master节点上部署

3.8.1 创建私钥和证书

[root@master1 ~]# vi controller-manager-csr.json


{
    "CN": "system:kube-controller-manager",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "hosts": [
      "127.0.0.1",
      "192.168.0.150",
      "192.168.0.151",
      "192.168.0.152"
    ],
    "names": [
      {
        "C": "CN",
        "ST": "SICHUAN",
        "L": "CHENGDU",
        "O": "system:kube-controller-manager",
        "OU": "system"
      }
    ]
}

生成私钥和证书

[root@master1 ~]# cfssl gencert -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -profile=kubernetes controller-manager-csr.json | cfssljson -bare controller-manager

分发到所有master节点

[root@master1 ~]# for i in master1 master2 master3; do scp controller-manager*.pem $i:/etc/kubernetes/pki/; done

3.8.2 创建controller-manager的kubeconfig

设置集群彩数

[root@master1 ~]# kubectl config set-cluster kubernetes \
  --certificate-authority=ca.pem \
  --embed-certs=true \
  --server=https://192.168.0.160:8443 \
  --kubeconfig=controller-manager.kubeconfig

设置客户端参数

[root@master1 ~]# kubectl config set-credentials system:kube-controller-manager \
  --client-certificate=controller-manager.pem \
  --client-key=controller-manager-key.pem \
  --embed-certs=true \
  --kubeconfig=controller-manager.kubeconfig

设置上下文

[root@master1 ~]# kubectl config set-context system:kube-controller-manager \
  --cluster=kubernetes \
  --user=system:kube-controller-manager \
  --kubeconfig=controller-manager.kubeconfig

设置默认上下文

[root@master1 ~]# kubectl config use-context system:kube-controller-manager --kubeconfig=controller-manager.kubeconfig

分发 controller-manager.kubeconfig 文件到每个 master节点

[root@master1 ~]# for i in master1 master2 master3; do scp controller-manager.kubeconfig $i:/etc/kubernetes/; done

3.8.3 创建 kube-controller-manager的systemd启动文件

[root@master1 ~]# vi kube-controller-manager.service

[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes

[Service]
ExecStart=/opt/kubernetes/bin/kube-controller-manager \
  --port=0 \
  --secure-port=10252 \
  --bind-address=127.0.0.1 \
  --kubeconfig=/etc/kubernetes/controller-manager.kubeconfig \
  --service-cluster-ip-range=10.255.0.0/16 \
  --cluster-name=kubernetes \
  --cluster-signing-cert-file=/etc/kubernetes/pki/ca.pem \
  --cluster-signing-key-file=/etc/kubernetes/pki/ca-key.pem \
  --allocate-node-cidrs=true \
  --cluster-cidr=172.23.0.0/16 \
  --experimental-cluster-signing-duration=87600h \
  --root-ca-file=/etc/kubernetes/pki/ca.pem \
  --service-account-private-key-file=/etc/kubernetes/pki/ca-key.pem \
  --leader-elect=true \
  --feature-gates=RotateKubeletServerCertificate=true \
  --controllers=*,bootstrapsigner,tokencleaner \
  --horizontal-pod-autoscaler-use-rest-clients=true \
  --horizontal-pod-autoscaler-sync-period=10s \
  --tls-cert-file=/etc/kubernetes/pki/controller-manager.pem \
  --tls-private-key-file=/etc/kubernetes/pki/controller-manager-key.pem \
  --use-service-account-credentials=true \
  --alsologtostderr=true \
  --logtostderr=false \
  --log-dir=/var/log/kubernetes \
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

kube-controller-manager.service分发到每个master节点

[root@master1 ~]#  for i in master1 master2 master3; do scp kube-controller-manager.service $i:/etc/systemd/system/; done

在每个master上启动 kube-controller-manager服务

$ systemctl daemon-reload && systemctl enable kube-controller-manager && systemctl restart kube-controller-manager

查看服务器状态

$ systemctl status kube-controller-manager

如果没有启动成功,查看日志

$ journalctl -f -u kube-controller-manager


3.9 部署 kube scheduler

在所有master节点上完成

3.9.1 创建私钥和证书

[root@master1 ~]# vi scheduler-csr.json


{
    "CN": "system:kube-scheduler",
    "hosts": [
      "127.0.0.1",
      "192.168.0.150",
      "192.168.0.151",
      "192.168.0.152"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
      {
        "C": "CN",
        "ST": "SICHUAN",
        "L": "CHENGDU",
        "O": "system:kube-scheduler",
        "OU": "system"
      }
    ]
}

生成私钥和证书

[root@master1 ~]# cfssl gencert -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -profile=kubernetes scheduler-csr.json | cfssljson -bare kube-scheduler

分发到每个 master 节点

[root@master1 ~]# for i in master1 master2 master3;do scp kube-scheduler*.pem $i:/etc/kubernetes/pki;done

3.9.2 创建kube scheduler的kubeconfig

设置集群参数

[root@master1 ~]# kubectl config set-cluster kubernetes \
  --certificate-authority=ca.pem \
  --embed-certs=true \
  --server=https://192.168.0.160:8443 \
  --kubeconfig=kube-scheduler.kubeconfig

设置客户端认证参数

[root@master1 ~]# kubectl config set-credentials system:kube-scheduler \
  --client-certificate=kube-scheduler.pem \
  --client-key=kube-scheduler-key.pem \
  --embed-certs=true \
  --kubeconfig=kube-scheduler.kubeconfig

设置上下文参数

[root@master1 ~]# kubectl config set-context system:kube-scheduler \
  --cluster=kubernetes \
  --user=system:kube-scheduler \
  --kubeconfig=kube-scheduler.kubeconfig

设置默认下下文

[root@master1 ~]# kubectl config use-context system:kube-scheduler --kubeconfig=kube-scheduler.kubeconfig

kube-scheduler.kubeconfig文件分发到每个 master节点上

[root@master1 ~]# for i in master1 master2 master3; do scp kube-scheduler.kubeconfig $i:/etc/kubernetes/; done

3.9.3 创建 kube-scheduler的systemd启动文件

创建 kube-scheduler.service 文件:

[root@master1 ~]# vi kube-scheduler.service

[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes

[Service]
ExecStart=/opt/kubernetes/bin/kube-scheduler \
  --address=127.0.0.1 \
  --kubeconfig=/etc/kubernetes/kube-scheduler.kubeconfig \
  --leader-elect=true \
  --alsologtostderr=true \
  --logtostderr=false \
  --log-dir=/var/log/kubernetes \
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

kube-scheduler.service文件分发到每个master节点上

[root@master1 ~]# for i in master1 master2 master3;do scp kube-scheduler.service $i:/etc/systemd/system/;done

3.9.4 启动kube-scheduler服务

在每个master节点上启动服务:

$ systemctl daemon-reload && systemctl enable kube-scheduler && systemctl restart kube-scheduler

查看服务状态:

$ systemctl status kube-scheduler

异常时,查看启动日志:

$ journalctl -f -u kube-scheduler


3.10 部署kubelet


$ docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause-amd64:3.2
$ docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause-amd64:3.2 k8s.gcr.io/pause-amd64:3.2
$ docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/pause-amd64:3.2

$ docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:1.7.0
$ docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:1.7.0 k8s.gcr.io/coredns:1.7.0
$ docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:1.7.0

在所有worker节点上完成

3.10.1 创建bootstrap配置文件

创建token并设置环境变量

[root@master1 ~]# export BOOTSTRAP_TOKEN=$(kubeadm token create \
      --description kubelet-bootstrap-token \
      --groups system:bootstrappers:worker \
      --kubeconfig kube.config)

创建 kube-bootstrap.kubeconfig

[root@master1 ~]# kubectl config set-cluster kubernetes \
      --certificate-authority=ca.pem \
      --embed-certs=true \
      --server=https://192.168.0.160:8443 \
      --kubeconfig=kubelet-bootstrap.kubeconfig

设置客户端认证参数

[root@master1 ~]# kubectl config set-credentials kubelet-bootstrap \
      --token=${BOOTSTRAP_TOKEN} \
      --kubeconfig=kubelet-bootstrap.kubeconfig

设置上下文参数

[root@master1 ~]# kubectl config set-context default \
      --cluster=kubernetes \
      --user=kubelet-bootstrap \
      --kubeconfig=kubelet-bootstrap.kubeconfig

设置默认上下文

[root@master1 ~]# kubectl config use-context default --kubeconfig=kubelet-bootstrap.kubeconfig

分发 kubelet-bootstrap.kubeconfigworker节点


# 创建目录
[root@master1 ~]# for i in node1 node2; do ssh $i "mkdir /etc/kubernetes/"; done

# 分发文件
[root@master1 ~]# for i in node1 node2; do scp kubelet-bootstrap.kubeconfig $i:/etc/kubernetes/kubelet-bootstrap.kubeconfig; done

分发证书和密钥文件到worker节点

# 创建证书目录
[root@master1 ~]# for i in node1 node2; do ssh $i "mkdir -p /etc/kubernetes/pki"; done

# 分发文件
[root@master1 ~]# for i in node1 node2; do scp ca.pem $i:/etc/kubernetes/pki/; done

3.10.2 创建kubelet配置文件


[root@master1 ~]# vi kubelet.config.json

{
  "kind": "KubeletConfiguration",
  "apiVersion": "kubelet.config.k8s.io/v1beta1",
  "authentication": {
    "x509": {
      "clientCAFile": "/etc/kubernetes/pki/ca.pem"
    },
    "webhook": {
      "enabled": true,
      "cacheTTL": "2m0s"
    },
    "anonymous": {
      "enabled": false
    }
  },
  "authorization": {
    "mode": "Webhook",
    "webhook": {
      "cacheAuthorizedTTL": "5m0s",
      "cacheUnauthorizedTTL": "30s"
    }
  },
  "address": "192.168.0.153",
  "port": 10250,
  "readOnlyPort": 10255,
  "cgroupDriver": "cgroupfs",
  "hairpinMode": "promiscuous-bridge",
  "serializeImagePulls": false,
  "featureGates": {
    "RotateKubeletClientCertificate": true,
    "RotateKubeletServerCertificate": true
  },
  "clusterDomain": "cluster.local.",
  "clusterDNS": ["10.255.0.2"]
}

kubelet.config.json配置文件分到到每个worker节点上

[root@master1 ~]# for i in node1 node2; do scp kubelet.config.json $i:/etc/kubernetes/; done

注意:分发完成后,需要修改配置文件中的address字段,为所在节点的内网IP

3.10.3 创建kubelet的systemd启动文件


[root@master1 ~]# vi kubelet.service


[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service

[Service]
WorkingDirectory=/var/lib/kubelet
ExecStart=/opt/kubernetes/bin/kubelet \
  --bootstrap-kubeconfig=/etc/kubernetes/kubelet-bootstrap.kubeconfig \
  --cert-dir=/etc/kubernetes/pki \
  --kubeconfig=/etc/kubernetes/kubelet.kubeconfig \
  --config=/etc/kubernetes/kubelet.config.json \
  --network-plugin=cni \
  --pod-infra-container-image=k8s.gcr.io/pause-amd64:3.2 \
  --alsologtostderr=true \
  --logtostderr=false \
  --log-dir=/var/log/kubernetes \
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

kubelet.service 分发到每个worker节点上

[root@master1 ~]# for i in node1 node2; do scp kubelet.service $i:/etc/systemd/system/; done

创建每个worker节点 kubelet工作目录

[root@master1 ~]# for i in node1 node2; do ssh $i "mkdir -p /var/lib/kubelet"; done

3.10.4 启动kubelet服务

bootstrap赋权,创建一个角色绑定


[root@master1 ~]#  ~]# kubectl create clusterrolebinding kubelet-bootstrap --clusterrole=system:node-bootstrapper --group=system:bootstrappers

在每个 worker节点启动 kubelet

$ systemctl daemon-reload && systemctl enable kubelet && systemctl restart kubelet

查看启动状态

$ systemctl status kubelet

如果没有启动成功,可以查看日志

$ journalctl -f -u kubelet

3.10.5 加入集群

确保 kubelet 服务启动成功后,查看两个worker节点的请求。

[root@master1 ~]# kubectl get csr

NAME                                                   AGE   SIGNERNAME                                    REQUESTOR                 CONDITION
node-csr-Wg5tb9HaItJp3pirkva2E4uLwW58gRyV68FIHCHqPPg   30s   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:wmp9un   Pending
node-csr-glVMjyBuo3vceYH4hCIrbi-YsguLuUSOaa1S_AMkFPo   29s   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:wmp9un   Pending

分别Approve(同意) 这两个请求:

[root@master1 ~]#  kubectl certificate approve node-csr-Wg5tb9HaItJp3pirkva2E4uLwW58gRyV68FIHCHqPPg

certificatesigningrequest.certificates.k8s.io/node-csr-Wg5tb9HaItJp3pirkva2E4uLwW58gRyV68FIHCHqPPg approved

[root@master1 ~]#  kubectl certificate approve node-csr-glVMjyBuo3vceYH4hCIrbi-YsguLuUSOaa1S_AMkFPo

certificatesigningrequest.certificates.k8s.io/node-csr-glVMjyBuo3vceYH4hCIrbi-YsguLuUSOaa1S_AMkFPo approved

此时执行,两个 worker节点已经加入,但是状态为 NotReady,说明还需要完成后续操作

[root@master1 ~]#  kubectl get node


NAME    STATUS     ROLES    AGE   VERSION
node1   NotReady   <none>   42s   v1.19.16
node2   NotReady   <none>   15s   v1.19.16

说明:因为 kubelet 没有部署在 master节点,所以 kubectl get node时看不到任何 master 节点



3.11 部署 kube-proxy 服务

worker节点完成

3.11.1 创建私钥和证书

创建 csr 文件

[root@master1 ~]# vi kube-proxy-csr.json

{
  "CN": "system:kube-proxy",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "SICHUAN",
      "L": "CHENGDU",
      "O": "k8s",
      "OU": "system"
    }
  ]
}

生成私钥和证书

[root@master1 ~]# 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文件

[root@master1 ~]# kubectl config set-cluster kubernetes \
  --certificate-authority=ca.pem \
  --embed-certs=true \
  --server=https://192.168.0.160:8443 \
  --kubeconfig=kube-proxy.kubeconfig

设置客户端认证参数

[root@master1 ~]#  kubectl config set-credentials kube-proxy \
  --client-certificate=kube-proxy.pem \
  --client-key=kube-proxy-key.pem \
  --embed-certs=true \
  --kubeconfig=kube-proxy.kubeconfig

设置上下文

[root@master1 ~]# kubectl config set-context default \
  --cluster=kubernetes \
  --user=kube-proxy \
  --kubeconfig=kube-proxy.kubeconfig

切换默认上下文

[root@master1 ~]# kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig

分发 kube-proxy.kubeconfig 文件到每个 worker节点

[root@master1 ~]# for i in node1 node2;do scp kube-proxy.kubeconfig $i:/etc/kubernetes/;done

3.11.2 创建和分发kube-proxy配置文件

创建 kube-proxy.config.yaml文件

[root@master1 ~]# vi kube-proxy.config.yaml

apiVersion: kubeproxy.config.k8s.io/v1alpha1
# 修改为所在节点的ip
bindAddress: {worker_ip}
clientConnection:
  kubeconfig: /etc/kubernetes/kube-proxy.kubeconfig
clusterCIDR: 172.23.0.0/16
# 修改为所在节点的ip
healthzBindAddress: {worker_ip}:10256
kind: KubeProxyConfiguration
# 修改为所在节点的ip
metricsBindAddress: {worker_ip}:10249
mode: "iptables"

注意: 其中的 {worker_ip} 为每个 worker 节点的内网IP,记得分发后修改

kube-proxy.config.yaml 文件分到到每个 worker节点上

[root@master1 ~]# for i in node1 node2;do scp kube-proxy.config.yaml $i:/etc/kubernetes/;done

3.11.3 创建和分发kube-proxy的systemd服务文件

kube-proxy.service文件内容


[root@master1 ~]# vi kube-proxy.service 

[Unit]
Description=Kubernetes Kube-Proxy Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target

[Service]
WorkingDirectory=/var/lib/kube-proxy
ExecStart=/opt/kubernetes/bin/kube-proxy \
  --config=/etc/kubernetes/kube-proxy.config.yaml \
  --alsologtostderr=true \
  --logtostderr=false \
  --log-dir=/var/log/kubernetes \
  --v=2
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

kube-proxy.service文件分发到 worker节点上:

[root@master1 ~]# for i in node1 node2;do scp kube-proxy.service $i:/etc/systemd/system/;done

3.11.4 启动kube-proxy服务

创建 kube-proxy 服务需要的工作及日志目录:

[root@master1 ~]# for i in node1 node2; do ssh $i "mkdir -p /var/lib/kube-proxy && mkdir -p /var/log/kubernetes"; done

在每个worker节点启动服务

$ systemctl daemon-reload && systemctl enable kube-proxy && systemctl restart kube-proxy

查看状态:

$ systemctl status kube-proxy

查看日志:

$ journalctl -f -u kube-proxy


3.12 部署CNI网络插件

本次官方的安装方式,使用部署 calico

创建 calico-rbac-kdd.yaml文件:

[root@master1 ~]# vi calico.rbac-kdd.yaml

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: calico-node
rules:
  - apiGroups: [""]
    resources:
      - namespaces
    verbs:
      - get
      - list
      - watch
  - apiGroups: [""]
    resources:
      - pods/status
    verbs:
      - update
  - apiGroups: [""]
    resources:
      - pods
    verbs:
      - get
      - list
      - watch
      - patch
  - apiGroups: [""]
    resources:
      - services
    verbs:
      - get
  - apiGroups: [""]
    resources:
      - endpoints
    verbs:
      - get
  - apiGroups: [""]
    resources:
      - nodes
    verbs:
      - get
      - list
      - update
      - watch
  - apiGroups: ["extensions"]
    resources:
      - networkpolicies
    verbs:
      - get
      - list
      - watch
  - apiGroups: ["networking.k8s.io"]
    resources:
      - networkpolicies
    verbs:
      - watch
      - list
  - apiGroups: ["crd.projectcalico.org"]
    resources:
      - globalfelixconfigs
      - felixconfigurations
      - bgppeers
      - globalbgpconfigs
      - bgpconfigurations
      - ippools
      - globalnetworkpolicies
      - globalnetworksets
      - networkpolicies
      - clusterinformations
      - hostendpoints
    verbs:
      - create
      - get
      - list
      - update
      - watch

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: calico-node
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: calico-node
subjects:
- kind: ServiceAccount
  name: calico-node
  namespace: kube-system

使用kubectl安装calico:

[root@master1 ~]# kubectl apply -f calico-rbac-kdd.yaml
[root@master1 ~]# kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

等待 worker节点pull好calico的image,状态主为:Running,表示部署成功

[root@master1 ~]# kubectl get pod --all-namespaces

NAMESPACE     NAME                                      READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-85c867d48-c6qlc   1/1     Running   0          15m
kube-system   calico-node-5z9nj                         1/1     Running   0          15m
kube-system   calico-node-8gfsn                         1/1     Running   0          15m


3.13 部署DNS插件 coredns

[root@master1 ~]# vi coredns.yaml


apiVersion: v1
kind: ServiceAccount
metadata:
  name: coredns
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:coredns
rules:
- apiGroups:
  - ""
  resources:
  - endpoints
  - services
  - pods
  - namespaces
  verbs:
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:coredns
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:coredns
subjects:
- kind: ServiceAccount
  name: coredns
  namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health {
          lameduck 5s
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
          fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        forward . /etc/resolv.conf {
          max_concurrent 1000
        }
        cache 30
        loop
        reload
        loadbalance
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: coredns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/name: "CoreDNS"
spec:
  # replicas: not specified here:
  # 1. Default is 1.
  # 2. Will be tuned in real time if DNS horizontal auto-scaling is turned on.
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  selector:
    matchLabels:
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        k8s-app: kube-dns
    spec:
      priorityClassName: system-cluster-critical
      serviceAccountName: coredns
      tolerations:
        - key: "CriticalAddonsOnly"
          operator: "Exists"
      nodeSelector:
        kubernetes.io/os: linux
      affinity:
         podAntiAffinity:
           preferredDuringSchedulingIgnoredDuringExecution:
           - weight: 100
             podAffinityTerm:
               labelSelector:
                 matchExpressions:
                   - key: k8s-app
                     operator: In
                     values: ["kube-dns"]
               topologyKey: kubernetes.io/hostname
      containers:
      - name: coredns
        image: coredns/coredns:1.7.0
        imagePullPolicy: IfNotPresent
        resources:
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        args: [ "-conf", "/etc/coredns/Corefile" ]
        volumeMounts:
        - name: config-volume
          mountPath: /etc/coredns
          readOnly: true
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        - containerPort: 9153
          name: metrics
          protocol: TCP
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            add:
            - NET_BIND_SERVICE
            drop:
            - all
          readOnlyRootFilesystem: true
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /ready
            port: 8181
            scheme: HTTP
      dnsPolicy: Default
      volumes:
        - name: config-volume
          configMap:
            name: coredns
            items:
            - key: Corefile
              path: Corefile
---
apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  annotations:
    prometheus.io/port: "9153"
    prometheus.io/scrape: "true"
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "CoreDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP: 10.255.0.2
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP
  - name: metrics
    port: 9153
    protocol: TCP

安装coredns

[root@master1 ~]# kubectl apply -f coredns.yaml

查看是否成功:

[root@master1 ~]# kubectl get pod --all-namespaces | grep coredns
kube-system   coredns-7bf4bd64bd-gsfpk                  1/1     Running   0          16m

查看集群中的节点状态:

[root@master1 ~]# kubectl get node
NAME    STATUS   ROLES    AGE   VERSION
node1   Ready    <none>   11d   v1.19.16
node2   Ready    <none>   11d   v1.19.16

其中STATUS状态都为 Ready表示安装成功