欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

二进制安装部署kubernetes集群---超详细教程

程序员文章站 2022-03-29 19:21:35
前言:本篇博客是博主踩过无数坑,反复查阅资料,一步步搭建完成后整理的个人心得,分享给大家~~~ 本文所需的安装包,都上传在我的网盘中,需要的可以打赏博主一杯咖啡钱,然后私密博主,博主会很快答复呦~ 00.组件版本和配置策略 00-01.组件版本 Kubernetes 1.10.4 Docker 18 ......

前言:本篇博客是博主踩过无数坑,反复查阅资料,一步步搭建完成后整理的个人心得,分享给大家~~~

本文所需的安装包,都上传在我的网盘中,需要的可以打赏博主一杯咖啡钱,然后私密博主,博主会很快答复呦~

00.组件版本和配置策略

00-01.组件版本

  • kubernetes 1.10.4
  • docker 18.03.1-ce
  • etcd 3.3.7
  • flanneld 0.10.0
  • 插件:
    • coredns
    • dashboard
    • heapster (influxdbgrafana)
    • metrics-server
    • efk (elasticsearchfluentdkibana)
  • 镜像仓库:
    • docker registry
    • harbor

 

00-02.主要配置策略

kube-apiserver

  • 使用 keepalived haproxy 实现 3 节点高可用;
  • 关闭非安全端口 8080 和匿名访问;
  • 在安全端口 6443 接收 https 请求;
  • 严格的认证和授权策略 (x509tokenrbac)
  • 开启 bootstrap token 认证,支持 kubelet tls bootstrapping
  • 使用 https 访问 kubeletetcd,加密通信;

kube-controller-manager

  • 3 节点高可用;
  • 关闭非安全端口,在安全端口 10252 接收 https 请求;
  • 使用 kubeconfig 访问 apiserver 的安全端口;
  • 自动 approve kubelet 证书签名请求 (csr),证书过期后自动轮转;
  • controller 使用自己的 serviceaccount 访问 apiserver

kube-scheduler

  • 3 节点高可用;
  • 使用 kubeconfig 访问 apiserver 的安全端口;

kubelet

  • 使用 kubeadm 动态创建 bootstrap token,而不是在 apiserver 中静态配置;
  • 使用 tls bootstrap 机制自动生成 client server 证书,过期后自动轮转;
  • kubeletconfiguration 类型的 json 文件配置主要参数;
  • 关闭只读端口,在安全端口 10250 接收 https 请求,对请求进行认证和授权,拒绝匿名访问和非授权访问;
  • 使用 kubeconfig 访问 apiserver 的安全端口;

kube-proxy

  • 使用 kubeconfig 访问 apiserver 的安全端口;
  • kubeproxyconfiguration 类型的 json 文件配置主要参数;
  • 使用 ipvs 代理模式;

集群插件:

  • dns:使用功能、性能更好的 coredns
  • dashboard:支持登录认证;
  • metricheapstermetrics-server,使用 https 访问 kubelet 安全端口;
  • logelasticsearchfluendkibana
  • registry 镜像库:docker-registryharbor

 

01.系统初始化

01-01.集群机器

  • kube-master192.168.10.108
  • kube-node1192.168.10.109
  • kube-node2192.168.10.110

本文档中的 etcd 集群、master 节点、worker 节点均使用这三台机器。

 

在每个服务器上都要执行以下全部操作,如果没有特殊指明,本文档的所有操作均在kube-master 节点上执行

01-02.主机名

1、设置永久主机名称,然后重新登录

$ sudo hostnamectl set-hostname kube-master

$ sudo hostnamectl set-hostname kube-node1

$ sudo hostnamectl set-hostname kube-node2

 

2、修改 /etc/hostname 文件,添加主机名和 ip 的对应关系:

$ vim /etc/hosts

192.168.10.108 kube-master

192.168.10.109 kube-node1

192.168.10.110 kube-node2

 

01-03.添加 k8s 和 docker 账户

1、在每台机器上添加 k8s 账户

$ sudo useradd -m k8s

$ sudo sh -c 'echo along |passwd k8s --stdin' #k8s 账户设置密码

 

2、修改visudo权限

$ sudo visudo #去掉%wheel all=(all) nopasswd: all这行的注释

$ sudo grep '%wheel.*nopasswd: all' /etc/sudoers

%wheel all=(all) nopasswd: all

 

3、将k8s用户归到wheel

$ gpasswd -a k8s wheel

adding user k8s to group wheel

$ id k8s

uid=1000(k8s) gid=1000(k8s) groups=1000(k8s),10(wheel)

 

4、在每台机器上添加 docker 账户,将 k8s 账户添加到 docker 组中,同时配置 dockerd 数(注:安装完docker才有):

$ sudo useradd -m docker

$ sudo gpasswd -a k8s docker

$ sudo mkdir -p /opt/docker/

$ vim /opt/docker/daemon.json   #可以后续部署docker时在操作

{

  "registry-mirrors": ["https://hub-mirror.c.163.com", "https://docker.mirrors.ustc.edu.cn"],

  "max-concurrent-downloads": 20

}

 

01-04.无密码 ssh 登录其它节点

1、生成秘钥对

[root@kube-master ~]# ssh-keygen #连续回车即可

 

2、将自己的公钥发给其他服务器

[root@kube-master ~]# ssh-copy-id root@kube-master

[root@kube-master ~]# ssh-copy-id root@kube-node1

[root@kube-master ~]# ssh-copy-id root@kube-node2

 

[root@kube-master ~]# ssh-copy-id k8s@kube-master

[root@kube-master ~]# ssh-copy-id k8s@kube-node1

[root@kube-master ~]# ssh-copy-id k8s@kube-node2

 

01-05.将可执行文件路径 /opt/k8s/bin 添加到 path 变量

在每台机器上添加环境变量:

$ sudo sh -c "echo 'path=/opt/k8s/bin:$path:$home/bin:$java_home/bin' >> /etc/profile.d/k8s.sh"

$ source /etc/profile.d/k8s.sh

 

01-06.安装依赖包

在每台机器上安装依赖包:

centos:

$ sudo yum install -y epel-release

$ sudo yum install -y conntrack ipvsadm ipset jq sysstat curl iptables libseccomp

 

ubuntu:

$ sudo apt-get install -y conntrack ipvsadm ipset jq sysstat curl iptables libseccomp

注:ipvs 依赖 ipset

 

01-07.关闭防火墙

在每台机器上关闭防火墙:

关闭服务,并设为开机不自启

$ sudo systemctl stop firewalld

$ sudo systemctl disable firewalld

清空防火墙规则

$ sudo iptables -f && sudo iptables -x && sudo iptables -f -t nat && sudo iptables -x -t nat

$ sudo iptables -p forward accept

 

01-08.关闭 swap 分区

1、如果开启了 swap 分区,kubelet 会启动失败(可以通过将参数 --fail-swap-on 设置为false 来忽略 swap on),故需要在每台机器上关闭 swap 分区:

$ sudo swapoff -a

 

2、为了防止开机自动挂载 swap 分区,可以注释 /etc/fstab 中相应的条目:

$ sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

 

01-09.关闭 selinux

1、关闭 selinux,否则后续 k8s 挂载目录时可能报错 permission denied

$ sudo setenforce 0

 

2、修改配置文件,永久生效;

$ grep selinux /etc/selinux/config

selinux=disabled

 

01-10.关闭 dnsmasq (可选)

linux 系统开启了 dnsmasq (gui 环境),将系统 dns server 设置为 127.0.0.1,这会导致 docker 容器无法解析域名,需要关闭它:

$ sudo service dnsmasq stop

$ sudo systemctl disable dnsmasq

 

01-11.加载内核模块

$ sudo modprobe br_netfilter

$ sudo modprobe ip_vs

 

01-12.设置系统参数

$ cat > kubernetes.conf <<eof

net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_recycle=0
vm.swappiness=0
vm.overcommit_memory=1
vm.panic_on_oom=0
fs.inotify.max_user_watches=89100
fs.file-max=52706963
fs.nr_open=52706963
net.ipv6.conf.all.disable_ipv6=1
net.netfilter.nf_conntrack_max=2310720

eof

$ sudo cp kubernetes.conf /etc/sysctl.d/kubernetes.conf

$ sudo sysctl -p /etc/sysctl.d/kubernetes.conf

$ sudo mount -t cgroup -o cpu,cpuacct none /sys/fs/cgroup/cpu,cpuacct

 

注:

  • tcp_tw_recycle kubernetes nat 冲突,必须关闭 ,否则会导致服务不通;
  • 关闭不使用的 ipv6 协议栈,防止触发 docker bug

 

01-13.设置系统时区

1、调整系统 timezone

$ sudo timedatectl set-timezone asia/shanghai

2、将当前的 utc 时间写入硬件时钟

$ sudo timedatectl set-local-rtc 0

3、重启依赖于系统时间的服务

$ sudo systemctl restart rsyslog

$ sudo systemctl restart crond

 

01-14.更新系统时间

$ yum -y install ntpdate

$ sudo ntpdate cn.pool.ntp.org

 

01-15.创建目录

在每台机器上创建目录:

$ sudo mkdir -p /opt/k8s/bin

$ sudo mkdir -p /opt/k8s/cert

$ sudo mkdir -p /opt/etcd/cert

$ sudo mkdir -p /opt/lib/etcd

$ sudo mkdir -p /opt/k8s/script

$ chown -r k8s /opt/*

 

01-16.检查系统内核和模块是否适合运行 docker (仅适用于linux 系统)

$ curl https://raw.githubusercontent.com/docker/docker/master/contrib/check-config.sh > check-config.sh

$ chmod +x check-config.sh

$ bash ./check-config.sh

 

02.创建 ca 证书和秘钥

  • 为确保安全, kubernetes 系统各组件需要使用 x509 证书对通信进行加密和认证。
  • ca (certificate authority) 是自签名的根证书,用来签名后续创建的其它证书。

本文档使用 cloudflare pki 工具集 cfssl 创建所有证书。

 

02-01.安装 cfssl 工具集

mkdir -p /opt/k8s/cert && sudo chown -r k8s /opt/k8s && cd /opt/k8s

wget https://pkg.cfssl.org/r1.2/cfssl_linux-amd64

mv cfssl_linux-amd64 /opt/k8s/bin/cfssl

wget https://pkg.cfssl.org/r1.2/cfssljson_linux-amd64

mv cfssljson_linux-amd64 /opt/k8s/bin/cfssljson

wget https://pkg.cfssl.org/r1.2/cfssl-certinfo_linux-amd64

mv cfssl-certinfo_linux-amd64 /opt/k8s/bin/cfssl-certinfo

chmod +x /opt/k8s/bin/*

 

02-02.创建根证书 (ca)

ca 证书是集群所有节点共享的,只需要创建一个 ca 证书,后续创建的所有证书都由它签名。

 

02-02-01 创建配置文件

ca 配置文件用于配置根证书的使用场景 (profile) 和具体参数 (usage,过期时间、服务端认证、客户端认证、加密等),后续在签名其它证书时需要指定特定场景。

[root@kube-master ~]# cd /opt/k8s/cert

[root@kube-master cert]# vim ca-config.json

{
    "signing": {
        "default": {
            "expiry": "87600h"
        },
        "profiles": {
            "kubernetes": {
                "usages": [
                    "signing",
                    "key encipherment",
                    "server auth",
                    "client auth"
                ],
                "expiry": "87600h"
            }
        }
    }
}

注:

① signing :表示该证书可用于签名其它证书,生成的 ca.pem 证书中ca=true

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

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

 

02-02-02 创建证书签名请求文件

[root@kube-master cert]# vim ca-csr.json

{
    "cn": "kubernetes",
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "c": "cn",
            "st": "beijing",
            "l": "beijing",
            "o": "k8s",
            "ou": "4paradigm"
        }
    ]
}

注:

① cncommon name kube-apiserver 从证书中提取该字段作为请求的用户名(user name),浏览器使用该字段验证网站是否合法;

② oorganization kube-apiserver 从证书中提取该字段作为请求用户所属的组(group)

③ kube-apiserver 将提取的 usergroup 作为 rbac 授权的用户标识;

 

02-02-03 生成 ca 证书和私钥

[root@kube-master cert]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca

[root@kube-master cert]# ls

ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem

 

02-02-04 分发证书文件

将生成的 ca 证书、秘钥文件、配置文件拷贝到所有节点的/opt/k8s/cert 目录下:

[root@kube-master ~]# vim /opt/k8s/script/scp_k8scert.sh

node_ips=("192.168.10.108" "192.168.10.109" "192.168.10.110")
for node_ip in ${node_ips[@]};do
    echo ">>> ${node_ip}"
    ssh root@${node_ip} "mkdir -p /opt/k8s/cert && chown -r k8s /opt/k8s"
    scp /opt/k8s/cert/ca*.pem /opt/k8s/cert/ca-config.json k8s@${node_ip}:/opt/k8s/cert
done

[root@kube-master ~]# chmod +x /opt/k8s/script/scp_k8scert.sh && /opt/k8s/script/scp_k8scert.sh

 

03.部署 kubectl 命令行工具

  kubectl kubernetes 集群的命令行管理工具,本文档介绍安装和配置它的步骤。

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

$ kubectl get pods

the connection to the server localhost:8080 was refused - did you specify the right host or port?

本文档只需要部署一次,生成的 kubeconfig 文件与机器无关。

 

03-01.下载kubectl 二进制文件

下载和解压

kubectl二进制文件需要*下载,我已经下载到我的网盘,有需要的小伙伴联系我~

[root@kube-master ~]# wget https://dl.k8s.io/v1.10.4/kubernetes-client-linux-amd64.tar.gz

[root@kube-master ~]# tar -xzvf kubernetes-client-linux-amd64.tar.gz

 

03-02.创建 admin 证书和私钥

  • kubectl apiserver https 安全端口通信,apiserver 对提供的证书进行认证和授权。
  • kubectl 作为集群的管理工具,需要被授予最高权限。这里创建具有最高权限的admin 证书。

03-02-01 创建证书签名请求

[root@kube-master ~]# cd /opt/k8s/cert/

cat > admin-csr.json <<eof

{
    "cn": "admin",
    "hosts": [],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "c": "cn",
            "st": "beijing",
            "l": "beijing",
            "o": "system:masters",
            "ou": "4paradigm"
        }
    ]
}

注:

① o system:masters kube-apiserver 收到该证书后将请求的 group 设置为system:masters

预定义的 clusterrolebinding cluster-admin group system:masters role cluster-admin 绑定,该 role 授予所有 api的权限;

该证书只会被 kubectl 当做 client 证书使用,所以 hosts 字段为空;

 

03-02-02 生成证书和私钥

[root@kube-master cert]# cfssl gencert -ca=/opt/k8s/cert/ca.pem \

-ca-key=/opt/k8s/cert/ca-key.pem \

-config=/opt/k8s/cert/ca-config.json \

-profile=kubernetes admin-csr.json | cfssljson_linux-amd64 -bare admin

 

[root@kube-master cert]# ls admin*

admin.csr admin-csr.json admin-key.pem admin.pem

 

03-03.创建和分发 kubeconfig 文件

03-03-01 创建kubeconfig文件

kubeconfig kubectl 的配置文件,包含访问 apiserver 的所有信息,如 apiserver 地址、ca 证书和自身使用的证书;

设置集群参数,(--server=${kube_apiserver} ,指定ip和端口;我使用的是haproxyvip和端口;如果没有haproxy代理,就用实际服务的ip和端口;如:https://192.168.10.108:6443

[root@kube-master ~]# kubectl config set-cluster kubernetes \

--certificate-authority=/opt/k8s/cert/ca.pem \

--embed-certs=true \

--server=https://192.168.10.10:8443 \

--kubeconfig=/root/.kube/kubectl.kubeconfig

设置客户端认证参数

[root@kube-master ~]# kubectl config set-credentials kube-admin \

--client-certificate=/opt/k8s/cert/admin.pem \

--client-key=/opt/k8s/cert/admin-key.pem \

--embed-certs=true \

--kubeconfig=/root/.kube/kubectl.kubeconfig

设置上下文参数

[root@kube-master ~]# kubectl config set-context kube-admin@kubernetes \

--cluster=kubernetes \

--user=kube-admin \

--kubeconfig=/root/.kube/kubectl.kubeconfig

设置默认上下文

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

 

注:在后续kubernetes认证,文章中会详细讲解

  • --certificate-authority :验证 kube-apiserver 证书的根证书;
  • --client-certificate --client-key :刚生成的 admin 证书和私钥,连接 kube-apiserver 时使用;
  • --embed-certs=true :将 ca.pem admin.pem 证书内容嵌入到生成的kubectl.kubeconfig 文件中(不加时,写入的是证书文件路径)

[root@kube-master ~]# chmod +x /opt/k8s/script/kubectl_environment.sh && /opt/k8s/script/kubectl_environment.sh

 

03-03-01 验证kubeconfig文件

[root@kube-master ~]# ls /root/.kube/kubectl.kubeconfig

/root/.kube/kubectl.kubeconfig

[root@kube-master ~]# kubectl config view --kubeconfig=/root/.kube/kubectl.kubeconfig

apiversion: v1
clusters:
- cluster:
    certificate-authority-data: redacted
    server: https://192.168.10.10:8443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kube-admin
  name: kube-admin@kubernetes
current-context: kube-admin@kubernetes
kind: config
preferences: {}
users:
- name: kube-admin
  user:
    client-certificate-data: redacted
    client-key-data: redacted

 

03-03-03 分发 kubeclt kubeconfig 文件,分发到所有使用kubectl 命令的节点

[root@kube-master ~]# vim /opt/k8s/script/scp_kubectl.sh

node_ips=("192.168.10.108" "192.168.10.109" "192.168.10.110")

node_ips=("192.168.10.108" "192.168.10.109" "192.168.10.110")
for node_ip in ${node_ips[@]};do
    echo ">>> ${node_ip}"
    scp /root/kubernetes/client/bin/kubectl k8s@${node_ip}:/opt/k8s/bin/
    ssh k8s@${node_ip} "chmod +x /opt/k8s/bin/*"
    ssh k8s@${node_ip} "mkdir -p ~/.kube"
    scp ~/.kube/config k8s@${node_ip}:~/.kube/config
    ssh root@${node_ip} "mkdir -p ~/.kube"
    scp ~/.kube/config root@${node_ip}:~/.kube/config
done

[root@kube-master ~]# chmod +x /opt/k8s/script/scp_kubectl.sh && /opt/k8s/script/scp_kubectl.sh

 

04.部署 etcd 集群

  etcd 是基于 raft 的分布式 key-value 存储系统,由 coreos 开发,常用于服务发现、共享配置以及并发控制(如 leader 选举、分布式锁等)。kubernetes 使用 etcd 存储所有运行数据。

本文档介绍部署一个三节点高可用 etcd 集群的步骤:

下载和分发 etcd 二进制文件

创建 etcd 集群各节点的 x509 证书,用于加密客户端(etcdctl) etcd 集群、etcd 集群之间的数据流;

创建 etcd systemd unit 文件,配置服务参数;

检查集群工作状态;

 

04-01.下载etcd 二进制文件

https://github.com/coreos/etcd/releases 页面下载最新版本的发布包:

[root@kube-master ~]# https://github.com/coreos/etcd/releases/download/v3.3.7/etcd-v3.3.7-linux-amd64.tar.gz

[root@kube-master ~]# tar -xvf etcd-v3.3.7-linux-amd64.tar.gz

 

04-02.创建 etcd 证书和私钥

04-02-01 创建证书签名请求

[root@kube-master ~]# cd /opt/etcd/cert

[root@kube-master cert]# cat > etcd-csr.json <<eof

{
    "cn": "etcd",
    "hosts": [
        "127.0.0.1",
        "192.168.10.108",
        "192.168.10.109",
        "192.168.10.110"
    ],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "c": "cn",
            "st": "beijing",
            "l": "beijing",
            "o": "k8s",
            "ou": "4paradigm"
        }
    ]
}

eof

注:hosts 字段指定授权使用该证书的 etcd 节点 ip 或域名列表,这里将 etcd 集群的三个节点 ip 都列在其中;

 

04-02-02 生成证书和私钥

[root@kube-master cert]# cfssl gencert -ca=/opt/k8s/cert/ca.pem \

-ca-key=/opt/k8s/cert/ca-key.pem \

-config=/opt/k8s/cert/ca-config.json \

-profile=kubernetes etcd-csr.json | cfssljson_linux-amd64 -bare etcd

 

[root@kube-master cert]# ls etcd*

etcd.csr etcd-csr.json etcd-key.pem etcd.pem

 

04-02-03 分发生成的证书和私钥到各 etcd 节点

[root@kube-master ~]# vim /opt/k8s/script/scp_etcd.sh

node_ips=("192.168.10.108" "192.168.10.109" "192.168.10.110")

for node_ip in ${node_ips[@]};do
        echo ">>> ${node_ip}"
        scp /root/etcd-v3.3.7-linux-amd64/etcd* k8s@${node_ip}:/opt/k8s/bin
        ssh k8s@${node_ip} "chmod +x /opt/k8s/bin/*"
        ssh root@${node_ip} "mkdir -p /opt/etcd/cert && chown -r k8s /opt/etcd/cert"
        scp /opt/etcd/cert/etcd*.pem k8s@${node_ip}:/opt/etcd/cert/
done

 

04-03.创建etcd 的systemd unit 模板及etcd 配置文件

04-03-01 创建etcd systemd unit 模板

[root@kube-master ~]# cat > /opt/etcd/etcd.service.template <<eof

[unit]
description=etcd server
after=network.target
after=network-online.target
wants=network-online.target
documentation=https://github.com/coreos
[service]
user=k8s
type=notify
workingdirectory=/opt/lib/etcd/
execstart=/opt/k8s/bin/etcd \
    --data-dir=/opt/lib/etcd \
    --name ##node_name## \
    --cert-file=/opt/etcd/cert/etcd.pem \
    --key-file=/opt/etcd/cert/etcd-key.pem \
    --trusted-ca-file=/opt/k8s/cert/ca.pem \
    --peer-cert-file=/opt/etcd/cert/etcd.pem \
    --peer-key-file=/opt/etcd/cert/etcd-key.pem \
    --peer-trusted-ca-file=/opt/k8s/cert/ca.pem \
    --peer-client-cert-auth \
    --client-cert-auth \
    --listen-peer-urls=https://##node_ip##:2380 \
    --initial-advertise-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=etcd0=https://192.168.10.108:2380,etcd1=https://192.168.10.109:2380,etcd2=https://192.168.10.110:2380 \
    --initial-cluster-state=new
restart=on-failure
restartsec=5
limitnofile=65536
[install]
wantedby=multi-user.target

eof

注:

  • user :指定以 k8s 账户运行;
  • workingdirectory --data-dir :指定工作目录和数据目录为/opt/lib/etcd ,需在启动服务前创建这个目录;
  • --name :指定节点名称,当 --initial-cluster-state 值为 new 时, --name 的参数值必须位于 --initial-cluster 列表中;
  • --cert-file --key-file etcd server client 通信时使用的证书和私钥;
  • --trusted-ca-file :签名 client 证书的 ca 证书,用于验证 client 证书;
  • --peer-cert-file --peer-key-file etcd peer 通信使用的证书和私钥;
  • --peer-trusted-ca-file :签名 peer 证书的 ca 证书,用于验证 peer 证书;

 

04-04.为各节点创建和分发 etcd systemd unit 文件

[root@kube-master ~]# cd /opt/k8s/script

[root@kube-master script]# vim etcd_service.sh

node_names=("etcd0" "etcd1" "etcd2")
node_ips=("192.168.10.108" "192.168.10.109" "192.168.10.110")
#替换模板文件中的变量,为各节点创建 systemd unit 文件
for (( i=0; i < 3; i++ ));do
        sed -e "s/##node_name##/${node_names[i]}/g" -e "s/##node_ip##/${node_ips[i]}/g" /opt/etcd/etcd.service.template > /opt/etcd/etcd-${node_ips[i]}.service
done
#分发生成的 systemd unit 和etcd的配置文件:
for node_ip in ${node_ips[@]};do
        echo ">>> ${node_ip}"
        ssh root@${node_ip} "mkdir -p /opt/lib/etcd && chown -r k8s /opt/lib/etcd"
        scp /opt/etcd/etcd-${node_ip}.service root@${node_ip}:/etc/systemd/system/etcd.service
done

[root@kube-master script]# chmod +x /opt/k8s/script/etcd_service.sh && /opt/k8s/script/etcd_service.sh

[root@kube-master script]# ls /opt/etcd/*.service

/opt/etcd/etcd-192.168.10.108.service /opt/etcd/etcd-192.168.10.110.service

/opt/etcd/etcd-192.168.10.109.service

[root@kube-master script]# ls /etc/systemd/system/etcd.service

/etc/systemd/system/etcd.service

 

04-05.启动 etcd 服务

[root@kube-master script]# vim /opt/k8s/script/etcd.sh

node_ips=("192.168.10.108" "192.168.10.109" "192.168.10.110")
#启动 etcd 服务
for node_ip in ${node_ips[@]};do
        echo ">>> ${node_ip}"
        ssh root@${node_ip} "systemctl daemon-reload && systemctl enable etcd && systemctl start etcd"
done
#检查启动结果,确保状态为 active (running)
for node_ip in ${node_ips[@]};do
        echo ">>> ${node_ip}"
        ssh k8s@${node_ip} "systemctl status etcd|grep active"
done
#验证服务状态,输出均为healthy 时表示集群服务正常
for node_ip in ${node_ips[@]};do
        echo ">>> ${node_ip}"
        etcdctl_api=3 /opt/k8s/bin/etcdctl \
--endpoints=https://${node_ip}:2379 \
--cacert=/opt/k8s/cert/ca.pem \
--cert=/opt/etcd/cert/etcd.pem \
--key=/opt/etcd/cert/etcd-key.pem endpoint health
done 

[root@kube-master script]# chmod +x etcd.sh && ./etcd.sh

>>> 192.168.10.108

created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /etc/systemd/system/etcd.service.

>>> 192.168.10.109

created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /etc/systemd/system/etcd.service.

>>> 192.168.10.110

created symlink from /etc/systemd/system/multi-user.target.wants/etcd.service to /etc/systemd/system/etcd.service.

#确保状态为 active (running),否则查看日志,确认原因:$ journalctl -u etcd

>>> 192.168.10.108

active: active (running) since mon 2018-11-26 17:41:00 cst; 12min ago

>>> 192.168.10.109

active: active (running) since mon 2018-11-26 17:41:00 cst; 12min ago

>>> 192.168.10.110

active: active (running) since mon 2018-11-26 17:41:01 cst; 12min ago

#输出均为healthy 时表示集群服务正常

>>> 192.168.10.108

https://192.168.10.108:2379 is healthy: successfully committed proposal: took = 1.373318ms

>>> 192.168.10.109

https://192.168.10.109:2379 is healthy: successfully committed proposal: took = 2.371807ms

>>> 192.168.10.110

https://192.168.10.110:2379 is healthy: successfully committed proposal: took = 1.764309ms

 

05.部署 flannel 网络

  • kubernetes 要求集群内各节点(包括 master 节点)能通过 pod 网段互联互通。flannel 使用 vxlan 技术为各节点创建一个可以互通的 pod 网络,使用的端口为 udp 8472,需要开放该端口(如公有云 aws 等)。
  • flannel 第一次启动时,从 etcd 获取 pod 网段信息,为本节点分配一个未使用的 /24段地址,然后创建 flannel.1 (也可能是其它名称,如 flannel1 等) 接口。
  • flannel 将分配的 pod 网段信息写入 /run/flannel/docker 文件,docker 后续使用这个文件中的环境变量设置 docker0 网桥。

 

05-01.下载flanneld 二进制文件

https://github.com/coreos/flannel/releases 页面下载最新版本的发布包:

[root@kube-master ~]# wget https://github.com/coreos/flannel/releases/download/v0.10.0/flannel-v0.10.0-linux-amd64.tar.gz

[root@kube-master ~]# tar -xzvf flannel-v0.10.0-linux-amd64.tar.gz -c flannel

 

05-02.创建 flannel 证书和私钥

flannel etcd 集群存取网段分配信息,而 etcd 集群启用了双向 x509 证书认证,所以需要为 flanneld 生成证书和私钥。

 

05-02-01 创建证书签名请求:

[root@kube-master ~]# cd /opt/flannel/cert

cat > flanneld-csr.json <<eof

{
    "cn": "flanneld",
    "hosts": [],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "c": "cn",
            "st": "beijing",
            "l": "beijing",
            "o": "k8s",
            "ou": "4paradigm"
        }
    ]
}

eof

该证书只会被 kubectl 当做 client 证书使用,所以 hosts 字段为空;

 

05-02-02 生成证书和私钥

[root@kube-master cert]# cfssl gencert -ca=/opt/k8s/cert/ca.pem \

-ca-key=/opt/k8s/cert/ca-key.pem \

-config=/opt/k8s/cert/ca-config.json \

-profile=kubernetes flanneld-csr.json | cfssljson -bare flanneld

[root@kube-master cert]# ls

flanneld.csr flanneld-csr.json flanneld-key.pem flanneld.pemls flanneld*pem

 

05-02-03 flanneld 二进制文件he1生成的证书和私钥分发到所有节点

cat > /opt/k8s/script/scp_flannel.sh <<eof

node_ips=("192.168.10.108" "192.168.10.109" "192.168.10.110")
for node_ip in ${node_ips[@]};do
    echo ">>> ${node_ip}"
    scp /root/flannel/{flanneld,mk-docker-opts.sh} k8s@${node_ip}:/opt/k8s/bin/
    ssh k8s@${node_ip} "chmod +x /opt/k8s/bin/*"
    ssh root@${node_ip} "mkdir -p /opt/flannel/cert && chown -r k8s /opt/flannel"
    scp /opt/flannel/cert/flanneld*.pem k8s@${node_ip}:/opt/flannel/cert
done

eof

 

05-03.向etcd 写入集群pod 网段信息

注意:本步骤只需执行一次。

[root@kube-master ~]# etcdctl \

--endpoints="https://192.168.10.108:2379,https://192.168.10.109:2379,https://192.168.10.110:2379" \

--ca-file=/opt/k8s/cert/ca.pem \

--cert-file=/opt/flannel/cert/flanneld.pem \

--key-file=/opt/flannel/cert/flanneld-key.pem \

set /atomic.io/network/config '{"network":"10.30.0.0/16","subnetlen": 24, "backend": {"type": "vxlan"}}'

{"network":"10.30.0.0/16","subnetlen": 24, "backend": {"type": "vxlan"}}

注:

  • flanneld 当前版本 (v0.10.0) 不支持 etcd v3,故使用 etcd v2 api 写入配置 key 和网段数据;
  • 写入的 pod 网段 "network" 必须是 /16 段地址,必须与kube-controller-manager --cluster-cidr 参数值一致;

 

05-04.创建 flanneld 的 systemd unit 文件

[root@kube-master ~]# cat > /opt/flannel/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=/opt/k8s/bin/flanneld \
-etcd-cafile=/opt/k8s/cert/ca.pem \
-etcd-certfile=/opt/flannel/cert/flanneld.pem \
-etcd-keyfile=/opt/flannel/cert/flanneld-key.pem \
-etcd-endpoints=https://192.168.10.108:2379,https://192.168.10.109:2379,https://192.168.10.110:2379 \
-etcd-prefix=/atomic.io/network \
-iface=eth1
execstartpost=/opt/k8s/bin/mk-docker-opts.sh -k docker_network_options -d /run/flannel/docker
restart=on-failure

[install]
wantedby=multi-user.target
requiredby=docker.service

 注:

  • mk-docker-opts.sh 脚本将分配给 flanneld pod 子网网段信息写入/run/flannel/docker 文件,后续 docker 启动时使用这个文件中的环境变量配置 docker0 网桥;
  • flanneld 使用系统缺省路由所在的接口与其它节点通信,对于有多个网络接口(如内网和公网)的节点,可以用 -iface