Kubernet 高可用集群搭建(上)

栏目: 编程工具 · 发布时间: 5年前

内容简介:还是采用CentOS 7 版本系统,由于启用了 TLS 双向认证、RBAC 授权等严格的安全机制,建议从头开始部署,否则可能会认证、授权等失败!修改 /etc/fstab 文件,注释掉 SWAP 的自动挂载,使用free -m确认swap已经关闭。所有节点需要设定/etc/host解析到所有主机。

前排前排:

近期公司忙于重构,线上和线下均采用K8S,且均为高可用架构。为了日后便于分析问题,也为了开源的精神,故将此篇文章分享于此。(还是采用个人虚拟机,资源有限,但是服务的部署还是一一涵盖的!)

还是采用CentOS 7 版本系统,由于启用了 TLS 双向认证、RBAC 授权等严格的安全机制,建议从头开始部署,否则可能会认证、授权等失败!

一、组件版本 && 集群环境

组件版本

  • Kubernetes 1.8.6
  • Docker 17.10.0-ce
  • Etcd 3.2.9
  • Flanneld
  • TLS 认证通信(所有组件,如etcd、kubernetes master 和node)
  • RBAC 授权
  • kubelet TLS Bootstrapping
  • kubedns、dashboard、heapster等插件
  • harbor,使用nfs后端存储

etcd 集群 && k8s master 机器 && k8s node 机器

IP Address Role 组件
192.168.161.161 master1 etcd,kube-scheduler,kube-controller-manager,kube-apiserver
192.168.161.162 master2 etcd,kube-scheduler,kube-controller-manager,kube-apiserver
192.168.161.163 master3 etcd,kube-scheduler,kube-controller-manager,kube-apiserver
192.168.161.164 node1 kube-proxy,kubelet,docker,flanneld
192.168.161.165 node2 kube-proxy,kubelet,docker,flanneld
192.168.161.200 vip api-server 高可用_ip

首先安装前要确认以下几项都已将准备完成:

  • 所有节点彼此网络互通,并且master1 SSH 登入其他节点为 passwdless。
  • 所有防火墙与 SELinux 已关闭。如 CentOS:
# systemctl stop firewalld && systemctl disable firewalld && setenforce 0 && sed -i '/SELINUX/s/enforcing/disabled/' /etc/selinux/config

关闭Swap

swapoff -a 
sed 's/.*swap.*/#&/' /etc/fstab

修改 /etc/fstab 文件,注释掉 SWAP 的自动挂载,使用free -m确认swap已经关闭。

所有节点需要设定/etc/host解析到所有主机。

192.168.161.161 master1
192.168.161.162 master2
192.168.161.163 master3
192.168.161.164 node1
192.168.161.165 node2

所有节点需要设定/etc/sysctl.d/k8s.conf的系统参数。

# cat <<EOF > /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

加载br_netfilter

# modprobe br_netfilter
# echo "modprobe br_netfilter" >> /etc/rc.local

刷新使之生效

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

设置iptables策略为 ACCEPT

# /sbin/iptables -P FORWARD ACCEPT

# echo  "sleep 60 && /sbin/iptables -P FORWARD ACCEPT" >> /etc/rc.local

安装依赖包

# yum install -y epel-release

# yum install -y yum-utils device-mapper-persistent-data lvm2 net-tools conntrack-tools wget

二、Kubernet 高可用集群搭建–创建证书

创建 CA 证书和秘钥

kubernetes 系统各组件需要使用 TLS 证书对通信进行加密,本文档使用 CloudFlare 的 PKI 工具集 cfssl 来生成 Certificate Authority (CA) 证书和秘钥文件,CA 是自签名的证书,用来签名后续创建的其它 TLS 证书。

生成的 CA 证书和秘钥文件如下:

ca-key.pem
ca.pem
kubernetes-key.pem
kubernetes.pem
kube-proxy.pem
kube-proxy-key.pem
admin.pem
admin-key.pem

使用证书的组件如下:

  • etcd:使用 ca.pem、kubernetes-key.pem、kubernetes.pem;
  • kube-apiserver:使用 ca.pem、kubernetes-key.pem、kubernetes.pem;
  • kubelet:使用 ca.pem;
  • kube-proxy:使用 ca.pem、kube-proxy-key.pem、kube-proxy.pem;
  • kubectl:使用 ca.pem、admin-key.pem、admin.pem;
  • kube-controller-manager:使用 ca-key.pem、ca.pem

以下操作都在 master 节点即 192.168.161.161 上执行,证书只需要创建一次即可,以后在向集群中添加新节点时只要将 /etc/kubernetes/ 目录下的证书拷贝到新节点上即可

安装 CFSSL

wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
chmod +x cfssl_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl

wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
chmod +x cfssljson_linux-amd64
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson

wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl-certinfo_linux-amd64
mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo

export PATH=/usr/local/bin:$PATH

创建 CA 配置文件

mkdir -p /etc/kubernetes/ssl && cd /etc/kubernetes/ssl
cat > ca-config.json << EOF
{
  "signing": {
    "default": {
      "expiry": "8760h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "8760h"
      }
    }
  }
}
EOF

ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;

signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;

server auth:表示 client 可以用该 CA 对 server 提供的证书进行验证;

client auth:表示 server 可以用该 CA 对 client 提供的证书进行验证;

创建 CA 证书签名请求:

cat > ca-csr.json << EOF
{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF

“CN”:Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法;

“O”:Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);

生成 CA 证书和私钥:

# cfssl gencert -initca ca-csr.json | cfssljson -bare ca

创建 kubernetes 证书签名请求文件:

已经被坑过一次了,一定要把所有的机器都添加进去包括虚拟IP

添加IP地址的时候,需要想到有个域名转发的nginx server也需要添加如下

也就是说 当你后期扩容节点的时候,如果你这边没有写扩容节点的IP,是不可以扩容的。

cat > kubernetes-csr.json << EOF
{
   "CN": "kubernetes",
    "hosts": [
      "127.0.0.1",
      "192.168.161.161",
      "192.168.161.162",
      "192.168.161.163",
      "192.168.161.200",
      "10.254.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": "BeiJing",
            "L": "BeiJing",
            "O": "k8s",
            "OU": "System"
        }
    ]
}
EOF
如上4个ip替换成自己服务器的ip。

hosts 中的内容可以为空,即使按照上面的配置,向集群中增加新节点后也不需要重新生成证书。

如果 hosts 字段不为空则需要指定授权使用该证书的 IP 或域名列表 ,由于该证书后续被 etcd 集群和 kubernetes master 集群使用,所以上面分别指定了 etcd 集群、kubernetes master 集群的主机 IP 和 kubernetes 服务的服务 IP (一般是 kue-apiserver 指定的 service-cluster-ip-range 网段的第一个IP,如 10.254.0.1。

生成 kubernetes 证书和私钥

# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes

# ls kubernetes*
kubernetes.csr  kubernetes-csr.json  kubernetes-key.pem  kubernetes.pem

创建 admin 证书

cat > admin-csr.json << EOF
{
  "CN": "admin",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "system:masters",
      "OU": "System"
    }
  ]
}
EOF
  • 后续 kube-apiserver 使用 RBAC 对客户端(如 kubelet、kube-proxy、Pod)请求进行授权;
  • kube-apiserver 预定义了一些 RBAC 使用的 RoleBindings,如 cluster-admin 将 Groupsystem:masters 与 Role cluster-admin 绑定,该 Role 授予了调用kube-apiserver 的 所有API的权限
  • OU 指定该证书的 Group 为 system:masters,kubelet 使用该证书访问 kube-apiserver时 ,由于证书被 CA 签名,所以认证通过,同时由于证书用户组为经过预授权的system:masters,所以被授予访问所有 API 的权限;

生成 admin 证书和私钥

# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin

# ls admin*
admin.csr  admin-csr.json  admin-key.pem  admin.pem

创建 kube-proxy 证书

cat > kube-proxy-csr.json << EOF
{
  "CN": "system:kube-proxy",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF
  • CN 指定该证书的 User 为 system:kube-proxy;
  • kube-apiserver 预定义的 RoleBinding cluster-admin 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;

生成 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

# ls kube-proxy*
kube-proxy.csr  kube-proxy-csr.json  kube-proxy-key.pem  kube-proxy.pem

校验证书

以 kubernetes 证书为例

使用 Opsnssl 命令

$ openssl x509  -noout -text -in  kubernetes.pem
...
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=Kubernetes
        Validity
            Not Before: Apr  5 05:36:00 2017 GMT
            Not After : Apr  5 05:36:00 2018 GMT
        Subject: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=kubernetes
...
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage:
                TLS Web Server Authentication, TLS Web Client Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier:
                DD:52:04:43:10:13:A9:29:24:17:3A:0E:D7:14:DB:36:F8:6C:E0:E0
            X509v3 Authority Key Identifier:
                keyid:44:04:3B:60:BD:69:78:14:68:AF:A0:41:13:F6:17:07:13:63:58:CD

            X509v3 Subject Alternative Name:
                DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster, DNS:kubernetes.default.svc.cluster.local, IP Address:127.0.0.1, IP Address:172.20.0.112, IP Address:172.20.0.113, IP Address:172.20.0.114, IP Address:172.20.0.115, IP Address:10.254.0.1
...
  • 确认 Issuer 字段的内容和 ca-csr.json 一致;
  • 确认 Subject 字段的内容和 kubernetes-csr.json 一致;
  • 确认 X509v3 Subject Alternative Name 字段的内容和 kubernetes-csr.json 一致;
  • 确认 X509v3 Key Usage、Extended Key Usage 字段的内容和 ca-config.json 中 kubernetesprofile 一致;

使用 Cfssl-Certinfo 命令

$ cfssl-certinfo -cert kubernetes.pem
...
{
  "subject": {
    "common_name": "kubernetes",
    "country": "CN",
    "organization": "k8s",
    "organizational_unit": "System",
    "locality": "BeiJing",
    "province": "BeiJing",
    "names": [
      "CN",
      "BeiJing",
      "BeiJing",
      "k8s",
      "System",
      "kubernetes"
    ]
  },
  "issuer": {
    "common_name": "Kubernetes",
    "country": "CN",
    "organization": "k8s",
    "organizational_unit": "System",
    "locality": "BeiJing",
    "province": "BeiJing",
    "names": [
      "CN",
      "BeiJing",
      "BeiJing",
      "k8s",
      "System",
      "Kubernetes"
    ]
  },
  "serial_number": "174360492872423263473151971632292895707129022309",
  "sans": [
    "kubernetes",
    "kubernetes.default",
    "kubernetes.default.svc",
    "kubernetes.default.svc.cluster",
    "kubernetes.default.svc.cluster.local",
    "127.0.0.1",
    "10.64.3.7",
    "10.254.0.1"
  ],
  "not_before": "2018-06-05T05:36:00Z",
  "not_after": "2019-06-05T05:36:00Z",
  "sigalg": "SHA256WithRSA",
...

分发证书

将生成的证书和秘钥文件(后缀名为.pem)拷贝到所有master和node节点的 /etc/kubernetes/ssl 目录下:

需要在所有的机器上面创建/etc/kubernetes/ssl目录

$ mkdir -p /etc/kubernetes/ssl

$ cp *.pem /etc/kubernetes/ssl

master1:

$ scp *.pem 192.168.161.162:/etc/kubernetes/ssl

$ scp *.pem 192.168.161.163:/etc/kubernetes/ssl

$ scp *.pem 192.168.161.164:/etc/kubernetes/ssl

$ scp *.pem 192.168.161.165:/etc/kubernetes/ssl

三、Kubernet 高可用集群搭建–Etcd集群

在三个节点都安装etcd,下面的操作需要在三个节点都执行一遍

下载etcd安装包

# wget https://github.com/coreos/etcd/releases/download/v3.2.12/etcd-v3.2.12-linux-amd64.tar.gz

# tar -xvf etcd-v3.2.12-linux-amd64.tar.gz

# sudo mv etcd-v3.2.12-linux-amd64/etcd* /usr/local/bin

创建工作目录

mkdir -p /var/lib/etcd      (根据实际业务场景,修改数据盘位置)

创建systemd unit 文件

当然 在其它两台机器上面的地址需要更改为另外两台机器的IP。

cat > etcd.service << EOF
[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=/usr/local/bin/etcd \\
  --name master1 \\
  --cert-file=/etc/kubernetes/ssl/kubernetes.pem \\
  --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \\
  --peer-cert-file=/etc/kubernetes/ssl/kubernetes.pem \\
  --peer-key-file=/etc/kubernetes/ssl/kubernetes-key.pem \\
  --trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\
  --peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem \\
  --initial-advertise-peer-urls https://192.168.161.161:2380 \\
  --listen-peer-urls https://192.168.161.161:2380 \\
  --listen-client-urls https://192.168.161.161:2379,http://127.0.0.1:2379 \\
  --advertise-client-urls https://192.168.161.161:2379 \\
  --initial-cluster-token etcd-cluster-0 \\
  --initial-cluster master1=https://192.168.161.161:2380,master2=https://192.168.161.162:2380,master3=https://192.168.161.163:2380 \\
  --initial-cluster-state new \\
  --data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF
如上的IP地址192.168.161.XXX 请逐一替换成你自己服务器的IP。

不要忽略name

下面给出常用配置的参数和它们的解释,方便理解:

--name:方便理解的节点名称,默认为 default,在集群中应该保持唯一,可以使用 hostname
--data-dir:服务运行数据保存的路径,默认为 ${name}.etcd
--snapshot-count:指定有多少事务(transaction)被提交时,触发截取快照保存到磁盘
--heartbeat-interval:leader 多久发送一次心跳到 followers。默认值是 100ms
--eletion-timeout:重新投票的超时时间,如果 follow 在该时间间隔没有收到心跳包,会触发重新投票,默认为 1000 ms
--listen-peer-urls:和同伴通信的地址,比如 http://ip:2380,如果有多个,使用逗号分隔。需要所有节点都能够访问,所以不要使用 localhost!
--listen-client-urls:对外提供服务的地址:比如 http://ip:2379,http://127.0.0.1:2379,客户端会连接到这里和 etcd 交互
--advertise-client-urls:对外公告的该节点客户端监听地址,这个值会告诉集群中其他节点
--initial-advertise-peer-urls:该节点同伴监听地址,这个值会告诉集群中其他节点
--initial-cluster:集群中所有节点的信息,格式为 node1=http://ip1:2380,node2=http://ip2:2380,…。注意:这里的 node1 是节点的 --name 指定的名字;后面的 ip1:2380 是 --initial-advertise-peer-urls 指定的值
--initial-cluster-state:新建集群的时候,这个值为 new;假如已经存在的集群,这个值为 existing
--initial-cluster-token:创建集群的 token,这个值每个集群保持唯一。这样的话,如果你要重新创建集群,即使配置和之前一样,也会再次生成新的集群和节点 uuid;否则会导致多个集群之间的冲突,造成未知的错误

所有以 –init 开头的配置都是在 bootstrap 集群的时候才会用到,后续节点的重启会被忽略。

NOTE:所有的参数也可以通过环境变量进行设置,–my-flag 对应环境变量的 ETCD_MY_FLAG;但是命令行指定的参数会覆盖环境变量对应的值。

指定 etcd 的工作目录为 /var/lib/etcd,数据目录为 /var/lib/etcd,需在启动服务前创建这个目录,否则启动服务的时候会报错“Failed at step CHDIR spawning /usr/bin/etcd: No such file or directory”;

为了保证通信安全,需要指定 etcd 的公私钥(cert-file和key-file)、Peers 通信的公私钥和 CA 证书(peer-cert-file、peer-key-file、peer-trusted-ca-file)、客户端的CA证书(trusted-ca-file);

创建 kubernetes.pem 证书时使用的 kubernetes-csr.json 文件的 hosts 字段包含所有 etcd 节点的IP,否则证书校验会出错;

–initial-cluster-state 值为 new 时,–name 的参数值必须位于 –initial-cluster 列表中;

启动 etcd 服务

cp etcd.service /etc/systemd/system/

systemctl daemon-reload

systemctl enable etcd

systemctl start etcd

systemctl status etcd
最先启动的 etcd 进程会卡住一段时间,等待其它节点上的 etcd 进程加入集群,为正常现象。

如上操作请确认一定要在三台机器上面都要执行;(单节点ETCD除外)

验证etcd服务,在任何一个etcd节点执行:

如果不添加密钥参数是会报错的:

[root@master1 ssl]# etcdctl cluster-health
failed to check the health of member 1d6f3edf4016ed5d on https://192.168.161.163:2379: Get https://192.168.161.163:2379/health: x509: certificate signed by unknown authority
member 1d6f3edf4016ed5d is unreachable: [https://192.168.161.163:2379] are all unreachable
failed to check the health of member 3d9715816751f109 on https://192.168.161.162:2379: Get https://192.168.161.162:2379/health: x509: certificate signed by unknown authority
member 3d9715816751f109 is unreachable: [https://192.168.161.162:2379] are all unreachable
failed to check the health of member d5fabdfaee58386c on https://192.168.161.161:2379: Get https://192.168.161.161:2379/health: x509: certificate signed by unknown authority
member d5fabdfaee58386c is unreachable: [https://192.168.161.161:2379] are all unreachable
cluster is unhealthy

使用密钥方式检查集群状态

[root@master1 ssl]# etcdctl \
    --ca-file=/etc/kubernetes/ssl/ca.pem \
    --cert-file=/etc/kubernetes/ssl/kubernetes.pem \
    --key-file=/etc/kubernetes/ssl/kubernetes-key.pem \
    cluster-health
    
member 1d6f3edf4016ed5d is healthy: got healthy result from https://192.168.161.163:2379
member 3d9715816751f109 is healthy: got healthy result from https://192.168.161.162:2379
member d5fabdfaee58386c is healthy: got healthy result from https://192.168.161.161:2379
cluster is healthy

部署 Flannel

在三个节点都安装Flannel,下面的操作需要在 三个节点都执行一遍

下载安装Flannel

# wget https://github.com/coreos/flannel/releases/download/v0.9.1/flannel-v0.9.1-linux-amd64.tar.gz

# mkdir flannel

# tar -xzvf flannel-v0.9.1-linux-amd64.tar.gz -C flannel

# cp flannel/{flanneld,mk-docker-opts.sh} /usr/local/bin

向 etcd 写入网段信息, 这两个命令只需要任意一个节点上执行一次就可以

etcdctl --endpoints=https://192.168.161.161:2379,https://192.168.161.162:2379,https://192.168.161.163:2379 \
--ca-file=/etc/kubernetes/ssl/ca.pem \
--cert-file=/etc/kubernetes/ssl/kubernetes.pem \
--key-file=/etc/kubernetes/ssl/kubernetes-key.pem \
mkdir /kubernetes/network

etcdctl --endpoints=https://192.168.161.161:2379,https://192.168.161.162:2379,https://192.168.161.163:2379 \
--ca-file=/etc/kubernetes/ssl/ca.pem \
--cert-file=/etc/kubernetes/ssl/kubernetes.pem \
--key-file=/etc/kubernetes/ssl/kubernetes-key.pem \
mk /kubernetes/network/config '{"Network":"172.30.0.0/16","SubnetLen":24,"Backend":{"Type":"vxlan"}}'

注意如上更换成自己的IP

创建systemd unit 文件 在 node机器上 面都需要执行

cat > flanneld.service << EOF
[Unit]
Description=Flanneld overlay address etcd agent
After=network.target
After=network-online.target
Wants=network-online.target
After=etcd.service
Before=docker.service

[Service]
Type=notify
ExecStart=/usr/local/bin/flanneld \\
  -etcd-cafile=/etc/kubernetes/ssl/ca.pem \\
  -etcd-certfile=/etc/kubernetes/ssl/kubernetes.pem \\
  -etcd-keyfile=/etc/kubernetes/ssl/kubernetes-key.pem \\
  -etcd-endpoints=https://192.168.161.161:2379,https://192.168.161.162:2379,https://192.168.161.163:2379 \\
  -etcd-prefix=/kubernetes/network
ExecStartPost=/usr/local/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker
Restart=on-failure

[Install]
WantedBy=multi-user.target
RequiredBy=docker.service
EOF

mk-docker-opts.sh 脚本将分配给 flanneld 的 Pod 子网网段信息写入到 /run/flannel/docker 文件中,后续 docker 启动时使用这个文件中参数值设置 docker0 网桥;

flanneld 使用系统缺省路由所在的接口和其它节点通信,对于有多个网络接口的机器(如,内网和公网),可以用 -iface=enpxx 选项值指定通信接口;

启动Flannel

mv flanneld.service /etc/systemd/system/

systemctl daemon-reload

systemctl enable flanneld

systemctl start flanneld

systemctl status flanneld

检查flannel服务状态

[root@master1 src]# /usr/local/bin/etcdctl  --endpoints=https://192.168.161.161:2379,https://192.168.161.162:2379,https://192.168.161.163:2379  --ca-file=/etc/kubernetes/ssl/ca.pem  --cert-file=/etc/kubernetes/ssl/kubernetes.pem  --key-file=/etc/kubernetes/ssl/kubernetes-key.pem  ls /kubernetes/network/subnets

/kubernetes/network/subnets/172.30.68.0-24
/kubernetes/network/subnets/172.30.46.0-24

四、Kubernet 高可用集群搭建–kubectl

部署 kubectl 工具,创建kubeconfig文件

kubectl是kubernetes的集群管理工具,任何节点通过kubetcl都可以管理整个k8s集群。

本文是在 master节点 部署,部署成功后会生成 /root/.kube/config 文件,kubectl就是通过这个获取 kube-apiserver 地址、证书、用户名等信息,所以这个文件需要保管好。

下载安装包

# cd /usr/local/src

# wget https://dl.k8s.io/v1.8.6/kubernetes-client-linux-amd64.tar.gz

# tar -xzvf kubernetes-client-linux-amd64.tar.gz

# sudo cp kubernetes/client/bin/kube* /usr/local/bin/

# chmod a+x /usr/local/bin/kube*

# export PATH=/usr/local/bin:$PATH

创建/root/.kube/config

# 设置集群参数,--server指定VIP的ip
kubectl config set-cluster kubernetes \
  --certificate-authority=/etc/kubernetes/ssl/ca.pem \
  --embed-certs=true \
  --server=https://192.168.161.200:6443

# 设置客户端认证参数
kubectl config set-credentials admin \
  --client-certificate=/etc/kubernetes/ssl/admin.pem \
  --embed-certs=true \
  --client-key=/etc/kubernetes/ssl/admin-key.pem

# 设置上下文参数
kubectl config set-context kubernetes \
  --cluster=kubernetes \
  --user=admin

# 设置默认上下文
kubectl config use-context kubernetes
注意:如上是注解,标注是后期更清晰些

admin.pem 证书 O 字段值为 system:masters,kube-apiserver 预定义的 RoleBinding cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予了调用kube-apiserver 相关 API 的权限

创建bootstrap.kubeconfig

kubelet访问kube-apiserver的时候是通过bootstrap.kubeconfig进行用户验证。

//生成token 变量
# export BOOTSTRAP_TOKEN=$(head -c 16 /dev/urandom | od -An -t x | tr -d ' ')

# cat > token.csv <<EOF
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF

分发 token.csv 文件

将 token.csv 文件拷贝到所有Master 和 Node的 /etc/kubernetes/ 目录:

$ cp token.csv /etc/kubernetes/

master01:

$ scp /etc/kubernetes/token.csv 192.168.161.162:/etc/kubernetes/

$ scp /etc/kubernetes/token.csv 192.168.161.163:/etc/kubernetes/

$ scp /etc/kubernetes/token.csv 192.168.161.164:/etc/kubernetes/

$ scp /etc/kubernetes/token.csv 192.168.161.165:/etc/kubernetes/

//设置集群参数--server为VIP节点ip
# kubectl config set-cluster kubernetes \
  --certificate-authority=/etc/kubernetes/ssl/ca.pem \
  --embed-certs=true \
  --server=https://192.168.161.200:6443 \
  --kubeconfig=bootstrap.kubeconfig

//设置客户端认证参数
# kubectl config set-credentials kubelet-bootstrap \
  --token=${BOOTSTRAP_TOKEN} \
  --kubeconfig=bootstrap.kubeconfig

//设置上下文参数
# kubectl config set-context default \
  --cluster=kubernetes \
  --user=kubelet-bootstrap \
  --kubeconfig=bootstrap.kubeconfig

//设置默认上下文
# kubectl config use-context default --kubeconfig=bootstrap.kubeconfig

# cp bootstrap.kubeconfig /etc/kubernetes/

创建kube-proxy.kubeconfig

# 设置集群参数 --server参数为 VIP的 ip
kubectl config set-cluster kubernetes \
  --certificate-authority=/etc/kubernetes/ssl/ca.pem \
  --embed-certs=true \
  --server=https://192.168.161.200:6443 \
  --kubeconfig=kube-proxy.kubeconfig

# 设置客户端认证参数
kubectl config set-credentials kube-proxy \
  --client-certificate=/etc/kubernetes/ssl/kube-proxy.pem \
  --client-key=/etc/kubernetes/ssl/kube-proxy-key.pem \
  --embed-certs=true \
  --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

# cp kube-proxy.kubeconfig /etc/kubernetes/

设置集群参数和客户端认证参数时 –embed-certs 都为 true,这会将 certificate-authority、client-certificate 和 client-key 指向的证书文件内容写入到生成的 kube-proxy.kubeconfig 文件中;

kube-proxy.pem 证书中 CN 为 system:kube-proxy,kube-apiserver 预定义的 RoleBinding cluster-admin 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;

分发 kubeconfig

将两个 kubeconfig 文件拷贝到所有 的 节点的 /etc/kubernetes/ 目录:

master01:

$ scp /etc/kubernetes/*.kubeconfig 192.168.161.164:/etc/kubernetes/

$ scp /etc/kubernetes/*.kubeconfig 192.161.161.165:/etc/kubernetes/

分发 kubeconfig 文件

将 ~/.kube/config 文件拷贝到运行 kubectl 命令的机器的 ~/.kube/ 目录下。

其它所有master和node节点创建目录:

$ mkdir -p /root/.kube

master01:

$ scp ~/.kube/config 192.168.161.162:/root/.kube

$ scp ~/.kube/config 192.168.161.163:/root/.kube

$ scp ~/.kube/config 192.168.161.164:/root/.kube

$ scp ~/.kube/config 192.168.161.165:/root/.kube

五、Kubernet 高可用集群搭建–master安装组件

下载安装文件

# wget https://dl.k8s.io/v1.8.6/kubernetes-server-linux-amd64.tar.gz

# tar -xzvf kubernetes-server-linux-amd64.tar.gz

# cp -r kubernetes/server/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl,kube-proxy,kubelet} /usr/local/bin/

配置和启动 kube-apiserver(两台master,master2上面直接修改master2的IP即可)

cat > kube-apiserver.service << EOF
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
After=etcd.service

[Service]
ExecStart=/usr/local/bin/kube-apiserver \\
  --logtostderr=true \\
  --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota,NodeRestriction \\
  --advertise-address=192.168.161.161 \\
  --bind-address=0.0.0.0 \\
  --insecure-bind-address=0.0.0.0 \\
  --authorization-mode=Node,RBAC \\
  --runtime-config=rbac.authorization.k8s.io/v1alpha1 \\
  --kubelet-https=true \\
  --enable-bootstrap-token-auth \\
  --token-auth-file=/etc/kubernetes/token.csv \\
  --service-cluster-ip-range=10.254.0.0/16 \\
  --service-node-port-range=8400-10000 \\
  --tls-cert-file=/etc/kubernetes/ssl/kubernetes.pem \\
  --tls-private-key-file=/etc/kubernetes/ssl/kubernetes-key.pem \\
  --client-ca-file=/etc/kubernetes/ssl/ca.pem \\
  --service-account-key-file=/etc/kubernetes/ssl/ca-key.pem \\
  --etcd-cafile=/etc/kubernetes/ssl/ca.pem \\
  --etcd-certfile=/etc/kubernetes/ssl/kubernetes.pem \\
  --etcd-keyfile=/etc/kubernetes/ssl/kubernetes-key.pem \\
  --etcd-servers=https://192.168.161.161:2379,https://192.168.161.162:2379,https://192.168.161.163: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/lib/audit.log \\
  --event-ttl=1h \\
  --v=2
Restart=on-failure
RestartSec=5
Type=notify
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

注意 更换成自己的IP

–authorization-mode=RBAC 指定在安全端口使用 RBAC 授权模式,拒绝未通过授权的请求;

kube-scheduler、kube-controller-manager 一般和 kube-apiserver 部署在同一台机器上,它们使用非安全端口和 kube-apiserver通信; 

kubelet、kube-proxy、kubectl 部署在其它 Node 节点上,如果通过安全端口访问 kube-apiserver,则必须先通过 TLS 证书认证,再通过 RBAC 授权; 

kube-proxy、kubectl 通过在使用的证书里指定相关的 User、Group 来达到通过 RBAC 授权的目的; 

如果使用了 kubelet TLS Boostrap 机制,则不能再指定 –kubelet-certificate-authority、–kubelet-client-certificate 和 –kubelet-client-key 选项,否则后续 kube-apiserver 校验 kubelet 证书时出现 ”x509: certificate signed by unknown authority“ 错误; 

–admission-control 值必须包含 ServiceAccount,否则部署集群插件时会失败;

–bind-address 不能为 127.0.0.1; 

–runtime-config配置为rbac.authorization.k8s.io/v1beta1,表示运行时的apiVersion;

–service-cluster-ip-range 指定 Service Cluster IP 地址段,该地址段不能路由可达; 

–service-node-port-range 指定 NodePort 的端口范围; 

缺省情况下 kubernetes 对象保存在 etcd /registry 路径下,可以通过 –etcd-prefix 参数进行调整;

启动 kube-apiserver

# cp kube-apiserver.service /etc/systemd/system/

systemctl daemon-reload

systemctl enable kube-apiserver

systemctl start kube-apiserver

systemctl status kube-apiserver

部署kube-apiserver 高可用

安装haproxy

$ yum install -y haproxy

配置haproxy

由于集群内部有的组建是通过非安全端口访问apiserver 的,有的是通过安全端口访问apiserver 的,所以我们要配置http 和https 两种代理方式,配置文件 /etc/haproxy/haproxy.cfg:( Master1和Master2上直接Copy此配置即可:

listen stats
  bind    *:9000
  mode    http
  stats   enable
  stats   hide-version
  stats   uri       /stats
  stats   refresh   30s
  stats   realm     Haproxy\ Statistics
  stats   auth      Admin:Password

frontend k8s-api
    bind 192.168.161.200:6443
    mode tcp
    option tcplog
    tcp-request inspect-delay 5s
    tcp-request content accept if { req.ssl_hello_type 1 }
    default_backend k8s-api

backend k8s-api
    mode tcp
    option tcplog
    option tcp-check
    balance roundrobin
    default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
    server k8s-api-1 192.168.161.161:6443 check
    server k8s-api-2 192.168.161.162:6443 check

frontend k8s-http-api
    bind 192.168.161.200:8080
    mode tcp
    option tcplog
    default_backend k8s-http-api

backend k8s-http-api
    mode tcp
    option tcplog
    option tcp-check
    balance roundrobin
    default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100
    server k8s-http-api-1 192.168.161.161:8080 check
    server k8s-http-api-2 192.168.161.162:8080 check

通过上面的配置文件我们可以看出通过https的访问将请求转发给apiserver 的6443端口了,http的请求转发到了apiserver 的8080端口。

启动haproxy

systemctl start haproxy
systemctl enable haproxy
systemctl status haproxy

然后我们可以通过上面9000端口监控我们的haproxy的运行状态(192.168.161.161:9000/stats):

Kubernet 高可用集群搭建(上)

上面我们的haproxy的确可以代理我们的两个master 上的apiserver 了,但是还不是高可用的,如果master01 这个节点down 掉了,那么我们haproxy 就不能正常提供服务了。这里我们可以使用两种方法来实现高可用

方式1:使用阿里云SLB(我们线上用的方式)

这种方式实际上是最省心的,在阿里云上建一个内网的SLB,将master01 与master02 添加到SLB 机器组中,转发80(http)和443(https)端口即可(注意下面的提示)

注意:阿里云的负载均衡是四层TCP负责,不支持后端ECS实例既作为Real Server又作为客户端向所在的负载均衡实例发送请求。因为返回的数据包只在云服务器内部转发,不经过负载均衡,所以在后端ECS实例上去访问负载均衡的服务地址是不通的。什么意思?就是如果你要使用阿里云的SLB的话,那么你不能在apiserver节点上使用SLB(比如在apiserver 上安装kubectl,然后将apiserver的地址设置为SLB的负载地址使用),因为这样的话就可能造成回环了,所以简单的做法是另外用两个新的节点做HA实例,然后将这两个实例添加到SLB 机器组中。

方式2:使用keepalived

KeepAlived 是一个高可用方案,通过 VIP(即虚拟 IP)和心跳检测来实现高可用。其原理是存在一组(两台)服务器,分别赋予 Master、Backup 两个角色,默认情况下Master 会绑定VIP 到自己的网卡上,对外提供服务。Master、Backup 会在一定的时间间隔向对方发送心跳数据包来检测对方的状态,这个时间间隔一般为 2 秒钟,如果Backup 发现Master 宕机,那么Backup 会发送ARP 包到网关,把VIP 绑定到自己的网卡,此时Backup 对外提供服务,实现自动化的故障转移,当Master 恢复的时候会重新接管服务。非常类似于路由器中的虚拟路由器冗余协议(VRRP)

Kubernet 高可用集群搭建(上)

开启路由转发,这里我们定义虚拟IP为: 192.168.161.200

$ vim /etc/sysctl.conf
# 添加以下内容
net.ipv4.ip_forward = 1
net.ipv4.ip_nonlocal_bind = 1

# 验证并生效
$ sysctl -p
# 验证是否生效
$ cat /proc/sys/net/ipv4/ip_forward
1

安装keepalived:

$ yum install -y keepalived

我们这里将master1 设置为Master,master2 设置为Backup,修改配置:

vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   notification_email {
   }
   router_id kube_api
}

vrrp_script check_k8s {
    # 自身状态检测
    script "/etc/keepalived/chk_k8s_master.sh"
    interval 3
    weight 5
}

vrrp_instance haproxy-vip {
    # 使用单播通信,默认是组播通信
    unicast_src_ip 192.168.161.161
    unicast_peer {
        192.168.161.162
    }
    # 初始化状态
    state BACKUP
    # 虚拟ip 绑定的网卡
    interface ens33
    # 此ID 要与Backup 配置一致
    virtual_router_id 51
    # 默认启动优先级,要比Backup 大点,但要控制量,保证自身状态检测生效
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        # 虚拟ip 地址
        192.168.161.200/24
    }
    track_script {
        check_k8s
    }
}

自身状态监测脚本,这里通过 api-server 是否在监听端口(6433 端口)来判断状态。

#!/bin/bash

d=`date --date today +%Y%m%d_%H:%M:%S`

n=`ps -C kube-apiserver --no-heading|wc -l`

if [ $n -eq "0" ]; then
        systemctl start kube-apiserver
        n2=`ps -C kube-apiserver --no-heading|wc -l`
        if [ $n2 -eq "0"  ]; then
                echo "$d Kube-apiserver down,keepalived will stop" >> /var/log/check_ng.log
                systemctl stop keepalived
        fi
fi

统一的方式 在master02 节点上安装keepalived,修改配置,只需要将state 更改成BACKUP,priority更改成99,unicast_src_ip 与unicast_peer 地址修改即可。

启动keepalived:

$ systemctl start keepalived
$ systemctl enable keepalived
# 查看日志
$ journalctl -f -u keepalived

查看IP

[root@master1 keepalived]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:26:e9:ae brd ff:ff:ff:ff:ff:ff
    inet 192.168.161.161/24 brd 192.168.161.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet 192.168.161.200/24 scope global secondary ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::2e63:8644:7484:a297/64 scope link 
       valid_lft forever preferred_lft forever

六、Kubernet 高可用集群搭建–Master组件

配置和启动 kube-controller-manager

scheduler,controller-manager在集群中只能在一台主机开启,这里我们可以在启动controller-manager和scheduler 只要加上 –leader-elect=true 参数就可以同时启动,系统会自动选举leader。

3台master部署controller-manager,以master1为例,替换各master的ip地址,serviceip范围和pod可获取的ip范围

cat > kube-controller-manager.service << EOF
[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/GoogleCloudPlatform/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-controller-manager \
  --logtostderr=true  \
  --address=127.0.0.1 \
  --master=https://192.168.161.200:6443 \
  --allocate-node-cidrs=true \
  --service-cluster-ip-range=10.254.0.0/16 \
  --cluster-cidr=172.30.0.0/16 \
  --cluster-name=kubernetes \
  --cluster-signing-cert-file=/etc/kubernetes/ssl/ca.pem \
  --cluster-signing-key-file=/etc/kubernetes/ssl/ca-key.pem \
  --service-account-private-key-file=/etc/kubernetes/ssl/ca-key.pem \
  --root-ca-file=/etc/kubernetes/ssl/ca.pem \
  --leader-elect=true \
  --v=2
Restart=on-failure
LimitNOFILE=65536
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

启动 kube-controller-manager

# cp kube-controller-manager.service /etc/systemd/system/

# systemctl daemon-reload

# systemctl enable kube-controller-manager

# systemctl start kube-controller-manager

三台部署scheduler,以master01为例,替换各master的ip地址

cat > kube-scheduler.service << EOF
[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/GoogleCloudPlatform/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-scheduler \\
  --logtostderr=true \\
  --address=127.0.0.1 \\
  --master=https://192.168.161.200:6443 \\
  --leader-elect=true \\
  --v=2
Restart=on-failure
LimitNOFILE=65536
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

启动 kube-scheduler

# cp kube-scheduler.service /etc/systemd/system/

# systemctl daemon-reload

# systemctl enable kube-scheduler

# systemctl start kube-scheduler

kube-controller-manager 和kube-scheduler 的高可用

Kubernetes 的管理层服务包括kube-scheduler和kube-controller-manager。kube-scheduler和kube-controller-manager使用一主多从的高可用方案, 在同一时刻只允许一个服务处以具体的任务 。Kubernetes中实现了一套简单的选主逻辑,依赖Etcd实现scheduler和controller-manager的选主功能。如果scheduler和controller-manager在启动的时候设置了 leader-elect参数 ,它们在启动后会先尝试获取leader节点身份,只有在获取leader节点身份后才可以执行具体的业务逻辑。它们分别会在Etcd中创建kube-scheduler和kube-controller-manager的endpoint,endpoint的信息中记录了当前的leader节点信息,以及记录的上次更新时间。leader节点会定期更新endpoint的信息,维护自己的leader身份。每个从节点的服务都会定期检查endpoint的信息,如果endpoint的信息在时间范围内没有更新,它们会尝试更新自己为leader节点。scheduler服务以及controller-manager服务之间不会进行通信,利用Etcd的强一致性,能够保证在分布式高并发情况下leader节点的全局唯一性。整体方案如下图所示:

Kubernet 高可用集群搭建(上)

当集群中的leader节点服务异常后,其它节点的服务会尝试更新自身为leader节点,当有多个节点同时更新endpoint时,由Etcd保证只有一个服务的更新请求能够成功。通过这种机制sheduler和controller-manager可以保证在leader节点宕机后其它的节点可以顺利选主,保证服务故障后快速恢复。当集群中的网络出现故障时对服务的选主影响不是很大, 因为scheduler和controller-manager是依赖Etcd进行选主的 ,在网络故障后,可以和Etcd通信的主机依然可以按照之前的逻辑进行选主,就算集群被切分,Etcd也可以保证同一时刻只有一个节点的服务处于leader状态。

验证 master 节点功能

Master1 上面:

[root@master1 ~]# kubectl get cs
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"}

Master2 上面:

[root@master2 ~]# kubectl get cs
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"}

以上所述就是小编给大家介绍的《Kubernet 高可用集群搭建(上)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

年入10万,17岁草根少年的网赚实战

年入10万,17岁草根少年的网赚实战

陶秋丰 / 重庆出版集团 / 2009-3 / 28.00元

《年入10万:17岁草根少年的网赚实战》以一个17岁的在校大学生的真实故事为大家讲述草根少年的网络赚钱之旅。随着网络的普及以及网上应用的日益增多,要在网络上谋生并不难,比如网上写稿、网上兼职、威客赚钱、网上开店等,然而要利用互联网赚大钱,并成就一番事业,那么创建并运营一个独立的网站就是一个绝佳的选择。本书的作者正是经历了“网上写稿一网上各类兼职一策划并创建网站一网站推广与运营一年入10万”这一过程......一起来看看 《年入10万,17岁草根少年的网赚实战》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具