牛骨文教育服务平台(让学习变的简单)
博文笔记

[K8S] 认证集群搭建

创建时间:2017-08-03 投稿人: 浏览次数:2860

注意:该文章 是 根据 https://github.com/opsnull/follow-me-install-kubernetes-cluster    (follow-me-install-kubernetes-cluster) 一步步做的。

若有版权问题请留言,谢谢!

其中自己根据实际情况做了若干变动。

里面的ip与实际对应如下(有的地方ip或许没改):

10.64.3.7

192.168.1.206

etcd-host0

10.64.3.8

192.168.1.207

etcd-host1

10.64.3.86

192.168.1.208

etcd-host2


01-组件版本和集群环境

集群组件和版本

  • Kubernetes 1.6.2
  • Docker 17.04.0-ce
  • Etcd 3.1.6
  • Flanneld 0.7.1 vxlan 网络
  • TLS 认证通信 (所有组件,如 etcd、kubernetes master 和 node)
  • RBAC 授权
  • kubelet TLS BootStrapping
  • kubedns、dashboard、heapster (influxdb、grafana)、EFK (elasticsearch、fluentd、kibana) 插件
  • 私有 docker registry,使用 ceph rgw 后端存储,TLS + HTTP Basic 认证

集群机器

  • 192.168.1.206

    master、registry 

    192.168.1.207 

    node01

    192.168.1.208

    node02

 

本着测试的目的,etcd 集群、kubernetes master 集群、kubernetesnode 均使用这三台机器。


初始化系统,关闭 firewalld selinux .

分发集群环境变量定义脚本

把全局变量定义脚本拷贝到所有机器的 /root/local/bin 目录:

$ cp environment.sh /root/local/bin

$ vi /etc/profile

source /root/local/bin/environment.sh

:wq

 

 

 

192.168.1.206  environment.sh

#!/usr/bin/bash

 

BOOTSTRAP_TOKEN="41f7e4ba8b7be874fcff18bf5cf41a7c"

 

# 最好使用 主机未用的网段 来定义服务网段和 Pod 网段

 

# 服务网段 (Service CIDR),部署前路由不可达,部署后集群内使用IP:Port可达

SERVICE_CIDR="10.254.0.0/16"

 

# POD 网段 (Cluster CIDR),部署前路由不可达,**部署后**路由可达(flanneld保证)

CLUSTER_CIDR="172.30.0.0/16"

 

# 服务端口范围 (NodePort Range)

export NODE_PORT_RANGE="8400-9000"

 

# etcd 集群服务地址列表

export ETCD_ENDPOINTS="https://192.168.1.206:2379,https://192.168.1.207:2379,https://192.168.1.208:2379"

 

# flanneld 网络配置前缀

export FLANNEL_ETCD_PREFIX="/kubernetes/network"

 

# kubernetes 服务 IP (一般是 SERVICE_CIDR 中第一个IP)

export CLUSTER_KUBERNETES_SVC_IP="10.254.0.1"

 

# 集群 DNS 服务 IP (从 SERVICE_CIDR 中预分配)

export CLUSTER_DNS_SVC_IP="10.254.0.2"

 

# 集群 DNS 域名

export CLUSTER_DNS_DOMAIN="cluster.local."

 

export NODE_NAME=etcd-host0 # 当前部署的机器名称(随便定义,只要能区分不同机器即可)

export NODE_IP=192.168.1.206 # 当前部署的机器 IP

export NODE_IPS="192.168.1.206 192.168.1.207 192.168.1.208" # etcd 集群所有机器 IP

# etcd 集群间通信的IP和端口

export ETCD_NODES=etcd-host0=https://192.168.1.206:2380,etcd-host1=https://192.168.1.207:2380,etcd-host2=https://192.168.1.208:2380

# 导入用到的其它全局变量:ETCD_ENDPOINTS、FLANNEL_ETCD_PREFIX、CLUSTER_CIDR

 

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

export MASTER_IP=192.168.1.206 # 替换为 kubernetes maste 集群任一机器 IP

export KUBE_APISERVER="https://${MASTER_IP}:6443"

 

 

192.168.1.207  environment.sh

#!/usr/bin/bash

 

BOOTSTRAP_TOKEN="41f7e4ba8b7be874fcff18bf5cf41a7c"

 

# 最好使用 主机未用的网段 来定义服务网段和 Pod 网段

 

# 服务网段 (Service CIDR),部署前路由不可达,部署后集群内使用IP:Port可达

SERVICE_CIDR="10.254.0.0/16"

 

# POD 网段 (Cluster CIDR),部署前路由不可达,**部署后**路由可达(flanneld保证)

CLUSTER_CIDR="172.30.0.0/16"

 

# 服务端口范围 (NodePort Range)

export NODE_PORT_RANGE="8400-9000"

 

# etcd 集群服务地址列表

export ETCD_ENDPOINTS="https://192.168.1.206:2379,https://192.168.1.207:2379,https://192.168.1.208:2379"

 

# flanneld 网络配置前缀

export FLANNEL_ETCD_PREFIX="/kubernetes/network"

 

# kubernetes 服务 IP (一般是 SERVICE_CIDR 中第一个IP)

export CLUSTER_KUBERNETES_SVC_IP="10.254.0.1"

 

# 集群 DNS 服务 IP (从 SERVICE_CIDR 中预分配)

export CLUSTER_DNS_SVC_IP="10.254.0.2"

 

# 集群 DNS 域名

export CLUSTER_DNS_DOMAIN="cluster.local."

 

export NODE_NAME=etcd-host1 # 当前部署的机器名称(随便定义,只要能区分不同机器即可)

export NODE_IP=192.168.1.207 # 当前部署的机器 IP

export NODE_IPS="192.168.1.206 192.168.1.207 192.168.1.208" # etcd 集群所有机器 IP

# etcd 集群间通信的IP和端口

export ETCD_NODES=etcd-host0=https://192.168.1.206:2380,etcd-host1=https://192.168.1.207:2380,etcd-host2=https://192.168.1.208:2380

# 导入用到的其它全局变量:ETCD_ENDPOINTS、FLANNEL_ETCD_PREFIX、CLUSTER_CIDR

 

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

export MASTER_IP=192.168.1.206 # 替换为 kubernetes maste 集群任一机器 IP

export KUBE_APISERVER="https://${MASTER_IP}:6443"

 

 

192.168.1.208  environment.sh

#!/usr/bin/bash

 

BOOTSTRAP_TOKEN="41f7e4ba8b7be874fcff18bf5cf41a7c"

 

# 最好使用 主机未用的网段 来定义服务网段和 Pod 网段

 

# 服务网段 (Service CIDR),部署前路由不可达,部署后集群内使用IP:Port可达

SERVICE_CIDR="10.254.0.0/16"

 

# POD 网段 (Cluster CIDR),部署前路由不可达,**部署后**路由可达(flanneld保证)

CLUSTER_CIDR="172.30.0.0/16"

 

# 服务端口范围 (NodePort Range)

export NODE_PORT_RANGE="8400-9000"

 

# etcd 集群服务地址列表

export ETCD_ENDPOINTS="https://192.168.1.206:2379,https://192.168.1.207:2379,https://192.168.1.208:2379"

 

# flanneld 网络配置前缀

export FLANNEL_ETCD_PREFIX="/kubernetes/network"

 

# kubernetes 服务 IP (一般是 SERVICE_CIDR 中第一个IP)

export CLUSTER_KUBERNETES_SVC_IP="10.254.0.1"

 

# 集群 DNS 服务 IP (从 SERVICE_CIDR 中预分配)

export CLUSTER_DNS_SVC_IP="10.254.0.2"

 

# 集群 DNS 域名

export CLUSTER_DNS_DOMAIN="cluster.local."

 

export NODE_NAME=etcd-host2 # 当前部署的机器名称(随便定义,只要能区分不同机器即可)

export NODE_IP=192.168.1.208 # 当前部署的机器 IP

export NODE_IPS="192.168.1.206 192.168.1.207 192.168.1.208" # etcd 集群所有机器 IP

# etcd 集群间通信的IP和端口

export ETCD_NODES=etcd-host0=https://192.168.1.206:2380,etcd-host1=https://192.168.1.207:2380,etcd-host2=https://192.168.1.208:2380

# 导入用到的其它全局变量:ETCD_ENDPOINTS、FLANNEL_ETCD_PREFIX、CLUSTER_CIDR

 

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

 

export MASTER_IP=192.168.1.206 # 替换为 kubernetes maste 集群任一机器 IP

export KUBE_APISERVER="https://${MASTER_IP}:6443"

 


02-创建CA证书和秘钥

创建 CA 证书和秘钥

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

安装 CFSSL

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

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

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

$ exportPATH=/root/local/bin:$PATH
$ mkdir ssl
$ cd ssl
$ cfssl print-defaults config >config.json
$ cfssl print-defaults csr > csr.json

以上工具每个节点都要安装

创建 CA (Certificate Authority)

创建 CA 配置文件:

$ cat ca-config.json
{
  "signing": {
    "default": {
      "expiry":"8760h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry":"8760h"
      }
    }
  }
}

  • 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
{
  "CN":"kubernetes",
  "key": {
    "algo":"rsa",
    "size": 2048
  },
  "names": [
    {
      "C":"CN",
      "ST":"BeiJing",
      "L":"BeiJing",
      "O":"k8s",
      "OU":"System"
    }
  ]
}

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

生成 CA 证书和私钥:

$ cfssl gencert -initca ca-csr.json| cfssljson -bare ca
$ ls ca*
ca-config.json  ca.csr  ca-csr.json ca-key.pem  ca.pem
$

分发证书

将生成的 CA 证书、秘钥文件、配置文件拷贝到所有机器的 /etc/kubernetes/ssl 目录下

$ sudo mkdir -p /etc/kubernetes/ssl
$ sudo cp ca* /etc/kubernetes/ssl
$

校验证书(这个是个例子)

以校验 kubernetes 证书(后续部署 master 节点时生成的)为例:

使用 openssl 命令

$ 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 2018GMT
        Subject: C=CN, ST=BeiJing,L=BeiJing, O=k8s, OU=System, CN=kubernetes
...
        X509v3 extensions:
            X509v3 Key Usage:critical
                Digital Signature, KeyEncipherment
            X509v3 Extended KeyUsage:
                TLS Web ServerAuthentication, TLS Web Client Authentication
            X509v3 Basic Constraints:critical
                CA:FALSE
            X509v3 Subject KeyIdentifier:
               DD:52:04:43:10:13:A9:29:24:17:3A:0E:D7:14:DB:36:F8:6C:E0:E0
            X509v3 Authority KeyIdentifier:
               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:10.64.3.7, 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 中 kubernetes profile 一致;

使用 cfssl-certinfo 命令

$ cfssl-certinfo -certkubernetes.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",
    "192.168.1.206",
    "192.168.1.207",
    "192.168.1.208",
    "10.254.0.1"
  ],
  "not_before":"2017-04-05T05:36:00Z",
  "not_after":"2018-04-05T05:36:00Z",
  "sigalg":"SHA256WithRSA",
...


03-部署高可用Etcd集群

部署高可用 etcd 集群

kuberntes 系统使用 etcd存储所有数据,本文档介绍部署一个三节点高可用 etcd 集群的步骤,这三个节点复用 kubernetes master 机器,分别命名为etcd-host0、etcd-host1、etcd-host2:

  • etcd-host0:192.168.1.206
  • etcd-host1:192.168.1.207
  • etcd-host2:192.168.1.208

使用的变量

本文档用到的变量定义如下(一开始已经加入environment.sh脚本里了):

$export NODE_NAME=etcd-host0#当前部署的机器名称(随便定义,只要能区分不同机器即可)
$ export NODE_IP=192.168.1.206# 当前部署的机器 IP
$ export NODE_IPS="192.168.1.206 192.168.1.207 192.168.1.208"# etcd 集群所有机器 IP
$ # etcd 集群间通信的IP和端口
$ export ETCD_NODES=etcd-host0=https://192.168.1.206:2380,etcd-host1=https://192.168.1.207:2380,etcd-host2=https://192.168.1.208:2380
$ #导入用到的其它全局变量:ETCD_ENDPOINTS、FLANNEL_ETCD_PREFIX、CLUSTER_CIDR
$ source /root/local/bin/environment.sh
$

下载二进制文件

到 https://github.com/coreos/etcd/releases 页面下载最新版本的二进制文件:

$ wgethttps://github.com/coreos/etcd/releases/download/v3.1.6/etcd-v3.1.6-linux-amd64.tar.gz
$ tar -xvf etcd-v3.1.6-linux-amd64.tar.gz
$ sudo mv etcd-v3.1.6-linux-amd64/etcd*/root/local/bin
$

创建 TLS 秘钥和证书

为了保证通信安全,客户端(如 etcdctl) 与 etcd 集群、etcd集群之间的通信需要使用 TLS 加密,本节创建 etcd TLS 加密所需的证书和私钥。

创建 etcd 证书签名请求:

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

  • hosts 字段指定授权使用该证书的 etcd 节点 IP;

生成 etcd 证书和私钥:

$ cfssl gencert-ca=/etc/kubernetes/ssl/ca.pem
  -ca-key=/etc/kubernetes/ssl/ca-key.pem
 -config=/etc/kubernetes/ssl/ca-config.json
  -profile=kubernetes etcd-csr.json | cfssljson -bare etcd
$ ls etcd*
etcd.csr  etcd-csr.json  etcd-key.pem etcd.pem
$ sudo mkdir -p /etc/etcd/ssl
$ sudo mv etcd*.pem /etc/etcd/ssl
$ rm etcd.csr  etcd-csr.json

创建 etcd 的 systemd unit 文件

$ sudo mkdir -p /var/lib/etcd # 必须先创建工作目录
$ 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=/root/local/bin/etcd\
  --name=${NODE_NAME} \
  --cert-file=/etc/etcd/ssl/etcd.pem \
  --key-file=/etc/etcd/ssl/etcd-key.pem \
  --peer-cert-file=/etc/etcd/ssl/etcd.pem \
  --peer-key-file=/etc/etcd/ssl/etcd-key.pem \
  --trusted-ca-file=/etc/kubernetes/ssl/ca.pem\
 --peer-trusted-ca-file=/etc/kubernetes/ssl/ca.pem \
 --initial-advertise-peer-urls=https://${NODE_IP}:2380 \
  --listen-peer-urls=https://${NODE_IP}:2380 \
 --listen-client-urls=https://${NODE_IP}:2379,http://127.0.0.1:2379 \
 --advertise-client-urls=https://${NODE_IP}:2379 \
  --initial-cluster-token=etcd-cluster-0 \
  --initial-cluster=${ETCD_NODES} \
  --initial-cluster-state=new \
  --data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

  • 指定 etcd 的工作目录和数据目录为 /var/lib/etcd,需在启动服务前创建这个目录;
  • 为了保证通信安全,需要指定 etcd 的公私钥(cert-file和key-file)、Peers 通信的公私钥和 CA 证书(peer-cert-file、peer-key-file、peer-trusted-ca-file)、客户端的CA证书(trusted-ca-file);
  • --initial-cluster-state 值为 new 时,--name 的参数值必须位于 --initial-cluster 列表中;

完整 unit 文件见:etcd.service

启动 etcd 服务

$ sudo mv etcd.service/etc/systemd/system/
$ sudo systemctl daemon-reload
$ sudo systemctl enable etcd
$ sudo systemctl start etcd
$ systemctl status etcd
$

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

在所有的 etcd 节点重复上面的步骤,直到所有机器的 etcd 服务都已启动。

验证服务

部署完 etcd 集群后,在任一 etcd 集群节点上执行如下命令:

$for ipin ${NODE_IPS}; do
  ETCDCTL_API=3 /root/local/bin/etcdctl
  --endpoints=https://${ip}:2379 
  --cacert=/etc/kubernetes/ssl/ca.pem
  --cert=/etc/etcd/ssl/etcd.pem
  --key=/etc/etcd/ssl/etcd-key.pem
  endpoint health; done

预期结果:

2017-07-0517:11:58.103401 I | warning: ignoring ServerName for user-provided CA forbackwards compatibility is deprecated

https://192.168.1.206:2379 is healthy:successfully committed proposal: took = 81.247077ms

2017-07-0517:11:58.356539 I | warning: ignoring ServerName for user-provided CA forbackwards compatibility is deprecated

https://192.168.1.207:2379 is healthy:successfully committed proposal: took = 12.073555ms

2017-07-0517:11:58.523829 I | warning: ignoring ServerName for user-provided CA forbackwards compatibility is deprecated

https://192.168.1.208:2379 is healthy:successfully committed proposal: took = 5.413361ms

 

04-部署Kubectl命令行工具

部署 kubectl 命令行工具

kubectl 默认从 ~/.kube/config 配置文件获取访问kube-apiserver 地址、证书、用户名等信息,如果没有配置该文件,执行命令时出错:

$ kubectl get pods
The connection to the server localhost:8080 was refused - did you specify theright host or port?

本文档介绍下载和配置 kubernetes 集群命令行工具 kubectl 的步骤。

需要将下载的 kubectl二进制程序和生成的 ~/.kube/config 配置文件拷贝到所有使用 kubectl命令的机器。

使用的变量

本文档用到的变量定义如下(一开始已经加入environment.sh脚本里了):

$export MASTER_IP=192.168.1.206   #在主节点 206上操作
$ export KUBE_APISERVER="https://${MASTER_IP}:6443"
$

  • 变量 KUBE_APISERVER 指定 kubelet 访问的 kube-apiserver 的地址,后续被写入 ~/.kube/config 配置文件;

下载 kubectl

$ wgethttps://dl.k8s.io/v1.6.2/kubernetes-client-linux-amd64.tar.gz
$ tar -xzvf kubernetes-client-linux-amd64.tar.gz
$ sudo cp kubernetes/client/bin/kube*/root/local/bin/
$ chmod a+x /root/local/bin/kube*
$ export PATH=/root/local/bin:$PATH
$

创建 admin 证书

kubectl 与 kube-apiserver 的安全端口通信,需要为安全通信提供 TLS证书和秘钥。

创建 admin 证书签名请求

$ cat admin-csr.json
{
  "CN":"admin",
  "hosts": [],
  "key": {
    "algo":"rsa",
    "size": 2048
  },
  "names": [
    {
      "C":"CN",
      "ST":"BeiJing",
      "L":"BeiJing",
      "O":"system:masters",
      "OU":"System"
    }
  ]
}

  • 后续 kube-apiserver 使用 RBAC 对客户端(如 kubelet、kube-proxy、Pod)请求进行授权;
  • kube-apiserver 预定义了一些 RBAC 使用的 RoleBindings,如 cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予了调用kube-apiserver 所有 API的权限;
  • O 指定该证书的 Group 为 system:masters,kubelet 使用该证书访问 kube-apiserver 时 ,由于证书被 CA 签名,所以认证通过,同时由于证书用户组为经过预授权的 system:masters,所以被授予访问所有 API 的权限;
  • hosts 属性值为空列表;

生成 admin 证书和私钥:

$ cfssl gencert-ca=/etc/kubernetes/ssl/ca.pem
  -ca-key=/etc/kubernetes/ssl/ca-key.pem
 -config=/etc/kubernetes/ssl/ca-config.json
  -profile=kubernetes admin-csr.json | cfssljson -bare admin
$ ls admin*
admin.csr  admin-csr.json  admin-key.pem admin.pem
$ sudo mv admin*.pem /etc/kubernetes/ssl/
$ rm admin.csr admin-csr.json
$

创建 kubectl kubeconfig 文件

$# 设置集群参数
$ kubectl config set-cluster kubernetes
 --certificate-authority=/etc/kubernetes/ssl/ca.pem
  --embed-certs=true
  --server=${KUBE_APISERVER}
$ # 设置客户端认证参数
$ 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 的权限;
  • 生成的 kubeconfig 被保存到 ~/.kube/config 文件;

分发 kubeconfig 文件

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



05-部署Flannel网络

部署 Flannel 网络

kubernetes 要求集群内各节点能通过 Pod 网段互联互通,本文档介绍使用Flannel 在所有节点 (Master、Node) 上创建互联互通的 Pod 网段的步骤。

使用的变量

本文档用到的变量定义如下:

$export NODE_IP=192.168.1.206# 当前部署节点的 IP
$ # 导入用到的其它全局变量:ETCD_ENDPOINTS、FLANNEL_ETCD_PREFIX、CLUSTER_CIDR
$ source /root/local/bin/environment.sh
$

创建 TLS 秘钥和证书

etcd 集群启用了双向 TLS 认证,所以需要为 flanneld 指定与 etcd集群通信的 CA 和秘钥。

创建 flanneld 证书签名请求:

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

  • hosts 字段为空;

生成 flanneld 证书和私钥:

$ cfssl gencert-ca=/etc/kubernetes/ssl/ca.pem
  -ca-key=/etc/kubernetes/ssl/ca-key.pem
 -config=/etc/kubernetes/ssl/ca-config.json
  -profile=kubernetes flanneld-csr.json | cfssljson -bare flanneld
$ ls flanneld*
flanneld.csr  flanneld-csr.json  flanneld-key.pem flanneld.pem
$ sudo mkdir -p /etc/flanneld/ssl
$ sudo mv flanneld*.pem /etc/flanneld/ssl
$ rm flanneld.csr  flanneld-csr.json

向 etcd 写入集群 Pod 网段信息

注意:本步骤只需在第一次部署 Flannel 网络时执行,后续在其它节点上部署 Flannel时无需再写入该信息!

$ /root/local/bin/etcdctl
  --endpoints=${ETCD_ENDPOINTS}
  --ca-file=/etc/kubernetes/ssl/ca.pem
  --cert-file=/etc/flanneld/ssl/flanneld.pem
 --key-file=/etc/flanneld/ssl/flanneld-key.pem
  set${FLANNEL_ETCD_PREFIX}/config"{"Network":""${CLUSTER_CIDR}"", "SubnetLen": 24, "Backend":{"Type": "vxlan"}}"

  • flanneld 目前版本 (v0.7.1) 不支持 etcd v3,故使用 etcd v2 API 写入配置 key 和网段数据;
  • 写入的 Pod 网段(${CLUSTER_CIDR},172.30.0.0/16) 必须与 kube-controller-manager 的 --cluster-cidr 选项值一致;

安装和配置 flanneld

下载 flanneld

$ mkdir flannel
$ wget https://github.com/coreos/flannel/releases/download/v0.7.1/flannel-v0.7.1-linux-amd64.tar.gz
$ tar -xzvf flannel-v0.7.1-linux-amd64.tar.gz -C flannel
$ sudo cp flannel/{flanneld,mk-docker-opts.sh} /root/local/bin
$

创建 flanneld 的 systemd unit 文件

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

[Service]
Type=notify
ExecStart=/root/local/bin/flanneld \
  -etcd-cafile=/etc/kubernetes/ssl/ca.pem\
 -etcd-certfile=/etc/flanneld/ssl/flanneld.pem \
 -etcd-keyfile=/etc/flanneld/ssl/flanneld-key.pem \
  -etcd-endpoints=${ETCD_ENDPOINTS}\
  -etcd-prefix=${FLANNEL_ETCD_PREFIX}
ExecStartPost=/root/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选项值指定通信接口(上面的 systemd unit 文件没指定这个选项);

完整 unit 见 flanneld.service

启动 flanneld

$ sudo cp flanneld.service/etc/systemd/system/
$ sudo systemctl daemon-reload
$ sudo systemctl enable flanneld
$ sudo systemctl start flanneld
$ systemctl status flanneld
$

检查 flanneld 服务

$ journalctl  -u flanneld|grep"Lease acquired"
$ ifconfig flannel.1
$

检查分配给各 flanneld 的 Pod 网段信息

$# 查看集群 Pod 网段(/16)
$ /root/local/bin/etcdctl
  --endpoints=${ETCD_ENDPOINTS}
  --ca-file=/etc/kubernetes/ssl/ca.pem
  --cert-file=/etc/flanneld/ssl/flanneld.pem
 --key-file=/etc/flanneld/ssl/flanneld-key.pem
  get${FLANNEL_ETCD_PREFIX}/config
{ "Network":"172.30.0.0/16","SubnetLen": 24,"Backend": {"Type":"vxlan" } }
$ # 查看已分配的 Pod 子网段列表(/24)
$ /root/local/bin/etcdctl
  --endpoints=${ETCD_ENDPOINTS}
  --ca-file=/etc/kubernetes/ssl/ca.pem
  --cert-file=/etc/flanneld/ssl/flanneld.pem
 --key-file=/etc/flanneld/ssl/flanneld-key.pem
  ls ${FLANNEL_ETCD_PREFIX}/subnets

 

2017-07-0517:27:46.007743 I | warning: ignoring ServerName for user-provided CA forbackwards compatibility is deprecated

/kubernetes/network/subnets/172.30.43.0-24

/kubernetes/network/subnets/172.30.44.0-24

/kubernetes/network/subnets/172.30.45.0-24


$ # 查看某一 Pod 网段对应的 flanneld 进程监听的 IP 和网络参数
$ /root/local/bin/etcdctl
  --endpoints=${ETCD_ENDPOINTS}
  --ca-file=/etc/kubernetes/ssl/ca.pem
  --cert-file=/etc/flanneld/ssl/flanneld.pem
 --key-file=/etc/flanneld/ssl/flanneld-key.pem
  get${FLANNEL_ETCD_PREFIX}/subnets/172.30.43.0-24

2017-07-0517:28:34.116874 I | warning: ignoring ServerName for user-provided CA forbackwards compatibility is deprecated

{"PublicIP":"192.168.1.207","BackendType":"vxlan","BackendData":{"VtepMAC":"52:73:8c:2f:ae:3c"}}

确保各节点间 Pod 网段能互联互通

在各节点上部署完 Flannel 后,查看已分配的 Pod 子网段列表(/24)

$ /root/local/bin/etcdctl
  --endpoints=${ETCD_ENDPOINTS}
  --ca-file=/etc/kubernetes/ssl/ca.pem
  --cert-file=/etc/flanneld/ssl/flanneld.pem
 --key-file=/etc/flanneld/ssl/flanneld-key.pem
  ls${FLANNEL_ETCD_PREFIX}/subnets
/kubernetes/network/subnets/172.30.43.0-24
/kubernetes/network/subnets/172.30.44.0-24
/kubernetes/network/subnets/172.30.45.0-24

当前三个节点分配的 Pod 网段分别是:172.30.43.0-24、172.30.44.0-24、172.30.45.0-24。


06-部署Master节点

部署 master 节点

kubernetes master 节点包含的组件:

  • kube-apiserver
  • kube-scheduler
  • kube-controller-manager

目前这三个组件需要部署在同一台机器上:

  • kube-scheduler、kube-controller-manager 和 kube-apiserver 三者的功能紧密相关;
  • 同时只能有一个 kube-scheduler、kube-controller-manager 进程处于工作状态,如果运行多个,则需要通过选举产生一个 leader;

本文档介绍部署单机 kubernetes master 节点的步骤,没有实现高可用master 集群。

计划后续再介绍部署 LB 的步骤,客户端(kubectl、kubelet、kube-proxy) 使用 LB 的 VIP 来访问 kube-apiserver,从而实现高可用 master 集群。

master 节点与 node 节点上的 Pods 通过 Pod 网络通信,所以需要在master 节点上部署 Flannel 网络。

使用的变量

本文档用到的变量定义如下:

$export MASTER_IP=192.168.1.206 # 替换为当前部署的 master 机器 IP
$ #导入用到的其它全局变量:SERVICE_CIDR、CLUSTER_CIDR、NODE_PORT_RANGE、ETCD_ENDPOINTS、BOOTSTRAP_TOKEN
$ source /root/local/bin/environment.sh
$

下载最新版本的二进制文件

有两种下载方式:

  1. 从 github release 页面 下载发布版 tarball,解压后再执行下载脚本
    $ wgethttps://github.com/kubernetes/kubernetes/releases/download/v1.6.2/kubernetes.tar.gz
    $ tar -xzvf kubernetes.tar.gz
    ...
    $ cd kubernetes
    $ ./cluster/get-kube-binaries.sh
    ...
  2. 从 CHANGELOG页面 下载 client 或 server tarball 文件
    server 的 tarball kubernetes-server-linux-amd64.tar.gz 已经包含了 client(kubectl) 二进制文件,所以不用单独下载kubernetes-client-linux-amd64.tar.gz文件;
    $# wgethttps://dl.k8s.io/v1.6.2/kubernetes-client-linux-amd64.tar.gz
    $ wget https://dl.k8s.io/v1.6.2/kubernetes-server-linux-amd64.tar.gz
    $ tar -xzvf kubernetes-server-linux-amd64.tar.gz
    ...
    $ cd kubernetes
    $ tar -xzvf  kubernetes-src.tar.gz

将二进制文件拷贝到指定路径:

$ sudo cp -rserver/bin/{kube-apiserver,kube-controller-manager,kube-scheduler,kubectl,kube-proxy,kubelet}/root/local/bin/
$

安装和配置 flanneld

参考 05-部署Flannel网络.md

创建 kubernetes 证书

创建 kubernetes 证书签名请求

$ cat>kubernetes-csr.json<<EOF
{
  "CN": "kubernetes",
  "hosts": [
    "127.0.0.1",
    "${MASTER_IP}",
    "${CLUSTER_KUBERNETES_SVC_IP}",
    "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

  • 如果 hosts 字段不为空则需要指定授权使用该证书的 IP 或域名列表,所以上面分别指定了当前部署的 master 节点主机 IP;
  • 还需要添加 kube-apiserver 注册的名为 kubernetes 的服务 IP (Service Cluster IP),一般是 kube-apiserver --service-cluster-ip-range 选项值指定的网段的第一个IP,如 "10.254.0.1";
    $ kubectl get svc kubernetes
    NAME         CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    kubernetes   10.254.0.1   <none>        443/TCP   1d

生成 kubernetes 证书和私钥

$ cfssl gencert-ca=/etc/kubernetes/ssl/ca.pem
  -ca-key=/etc/kubernetes/ssl/ca-key.pem
 -config=/etc/kubernetes/ssl/ca-config.json
  -profile=kubernetes kubernetes-csr.json| cfssljson -bare kubernetes
$ ls kubernetes*
kubernetes.csr  kubernetes-csr.json  kubernetes-key.pem  kubernetes.pem
$ sudo mkdir -p /etc/kubernetes/ssl/
$ sudo mv kubernetes*.pem /etc/kubernetes/ssl/
$ rm kubernetes.csr  kubernetes-csr.json

配置和启动 kube-apiserver

创建 kube-apiserver 使用的客户端 token 文件

kubelet 首次启动时向 kube-apiserver发送 TLS Bootstrapping 请求,kube-apiserver 验证 kubelet 请求中的 token 是否与它配置的 token.csv一致,如果一致则自动为 kubelet生成证书和秘钥。(这个token只要master做一次)

$# 导入的 environment.sh 文件定义了 BOOTSTRAP_TOKEN 变量
$ cat > token.csv<<EOF
${BOOTSTRAP_TOKEN},kubelet-bootstrap,10001,"system:kubelet-bootstrap"
EOF
$ mv token.csv /etc/kubernetes/
$

创建 kube-apiserver 的 systemd unit 文件

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

[Service]
ExecStart=/root/local/bin/kube-apiserver\
 --admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota\
  --advertise-address=${MASTER_IP} \
  --bind-address=${MASTER_IP} \
  --insecure-bind-address=${MASTER_IP} \
  --authorization-mode=RBAC \
 --runtime-config=rbac.authorization.k8s.io/v1alpha1 \
  --kubelet-https=true \
  --experimental-bootstrap-token-auth \
  --token-auth-file=/etc/kubernetes/token.csv\
  --service-cluster-ip-range=${SERVICE_CIDR} \
  --service-node-port-range=${NODE_PORT_RANGE}\
 --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=${ETCD_ENDPOINTS} \
  --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

  • kube-apiserver 1.6 版本开始使用 etcd v3 API 和存储格式;
  • --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;
  • --service-cluster-ip-range 指定 Service Cluster IP 地址段,该地址段不能路由可达;
  • --service-node-port-range=${NODE_PORT_RANGE} 指定 NodePort 的端口范围;
  • 缺省情况下 kubernetes 对象保存在 etcd /registry 路径下,可以通过 --etcd-prefix 参数进行调整;

完整 unit 见 kube-apiserver.service

启动 kube-apiserver

$ sudo cp kube-apiserver.service/etc/systemd/system/
$ sudo systemctl daemon-reload
$ sudo systemctl enable kube-apiserver
$ sudo systemctl start kube-apiserver
$ sudo systemctl status kube-apiserver
$

配置和启动 kube-controller-manager

创建 kube-controller-manager 的 systemd unit 文件

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

[Service]
ExecStart=/root/local/bin/kube-controller-manager\
  --address=127.0.0.1 \
  --master=http://${MASTER_IP}:8080 \
  --allocate-node-cidrs=true \
  --service-cluster-ip-range=${SERVICE_CIDR} \
  --cluster-cidr=${CLUSTER_CIDR} \
  --cluster-name=k

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。