0. 前言
- 上一篇中,我们介绍了多节点部署 kubernetes 集群,并通过 haproxy+keepalived 实现 Master 节点的负载均衡
- 其中 haproxy+keepalived 以 tcp 模式实现了正向代理和负载均衡
- 其实 haproxy 可以采用 http 模式工作,并通过 option redispatch 配置实现后端某个真实服务器挂掉后重新转发请求
- 但是如果我们希望实现在特定 http 状态码出现时,重试请求
- 因此本篇文章我们采用 nginx 作为负载均衡组件
1. 实验环境
- 实验环境主要为 4 台虚拟机,IP 地址分别为:192.168.1.66、192.168.1.67、192.168.1.68、192.168.1.69
1.1 节点分配
- 节点分配同上一篇文章,但是因为只有一个负载均衡节点,我们去掉了 lb1 节点
- LB 节点:
- lb2:192.168.1.66
- Master 节点:
- master1:192.168.1.67
- master2:192.168.1.68
- master3:192.168.1.69
- Node 节点:
- node1:192.168.1.67
- node2:192.168.1.68
- node3:192.168.1.69
- Etcd 节点:
- etcd01:192.168.1.67
- etcd02:192.168.1.68
- etcd03:192.168.1.69
- 为节约计算资源,kubernetes 集群中的 Master 节点、Node 节点和 Etcd 节点均各自部署在一个节点内
2. 部署流程
- 本章中,我们在 github 仓库 中补充了新的脚本
- 仓库中,nginx 分别实现了 http 和 http s 的方式启动,脚本分别放在 http_script 和 https_scripts 目录
- 其中 2.1 源码编译和 2.2 安装 docker 和上一篇文章中相同,熟悉的读者可以直接跳过
2.1 源码编译
- 安装 golang 环境
- kubernetes v1.18 要求使用的 golang 版本为 1.13
$ wget https://dl.google.com/go/go1.13.8.linux-amd64.tar.gz $ tar -zxvf go1.13.8.linux-amd64.tar.gz -C /usr/local/
- 添加如下环境变量至 ~/.bashrc 或者 ~/.zshrc
export GOROOT=/usr/local/go
# GOPATH
export GOPATH=$HOME/go
# GOROOT bin
export PATH=$PATH:$GOROOT/bin
# GOPATH bin
export PATH=$PATH:$GOPATH/bin
- 更新环境变量
$ source ~/.bashrc
- 从 github 上下载 kubernetes 最新源码
$ git clone https://github.com/kubernetes/kubernetes.git
- 编译形成二进制文件
$ make KUBE_BUILD_PLATFORMS=linux/amd64
+++ [0215 22:16:44] Building go targets for linux/amd64:
./vendor/k8s.io/code-generator/cmd/deepcopy-gen
+++ [0215 22:16:52] Building go targets for linux/amd64:
./vendor/k8s.io/code-generator/cmd/defaulter-gen
+++ [0215 22:17:00] Building go targets for linux/amd64:
./vendor/k8s.io/code-generator/cmd/conversion-gen
+++ [0215 22:17:12] Building go targets for linux/amd64:
./vendor/k8s.io/kube-openapi/cmd/openapi-gen
+++ [0215 22:17:25] Building go targets for linux/amd64:
./vendor/github.com/go-bindata/go-bindata/go-bindata
+++ [0215 22:17:27] Building go targets for linux/amd64:
cmd/kube-proxy
cmd/kube-apiserver
cmd/kube-controller-manager
cmd/kubelet
cmd/kubeadm
cmd/kube-scheduler
vendor/k8s.io/apiextensions-apiserver
cluster/gce/gci/mounter
cmd/kubectl
cmd/gendocs
cmd/genkubedocs
cmd/genman
cmd/genyaml
cmd/genswaggertypedocs
cmd/linkcheck
vendor/github.com/onsi/ginkgo/ginkgo
test/e2e/e2e.test
cluster/images/conformance/go-runner
cmd/kubemark
vendor/github.com/onsi/ginkgo/ginkgo
- KUBE_BUILD_PLATFORMS 指定了编译生成的二进制文件的目标平台,包括 darwin/amd64、linux/amd64 和 windows/amd64 等
- 执行 make cross 会生成所有平台的二进制文件
- 本地编译然后上传至服务器
- 生成的 _output 目录即为编译生成文件,核心二进制文件在 _output/local/bin/linux/amd64 中
$ pwd
/root/Coding/kubernetes/_output/local/bin/linux/amd64
$ ls
apiextensions-apiserver genman go-runner kube-scheduler kubemark
e2e.test genswaggertypedocs kube-apiserver kubeadm linkcheck
gendocs genyaml kube-controller-manager kubectl mounter
genkubedocs ginkgo kube-proxy kubelet
- 其中 kube-apiserver、kube-scheduler、kube-controller-manager、kubectl、kube-proxy 和 kubelet 为安装需要的二进制文件
2.2 安装 docker
- 在 kubernetes 集群的三个虚拟机上安装 docker:192.168.1.67、192.168.1.68、192.168.1.69
- 具体安装细节参见 官方文档
2.3 下载安装脚本
- 后续安装部署的所有脚本已经上传至 github 仓库 中,感兴趣的朋友可以下载
- 在 master1、master2 和 master3 上创建工作目录 k8s 以及脚本目录(k8s/scripts、k8s/http_scripts 和 k8s/https_scripts),复制相应的脚本,到工作目录中的脚本文件夹中
$ git clone https://github.com/wangao1236/k8s_cluster_deploy.git $ cd k8s_cluster_deploy/scripts $ chmod +x *.sh $ cd ~ $ mkdir -p k8s/scripts $ cp k8s_cluster_deploy/scripts/* k8s/scripts $ cd k8s_cluster_deploy/http_scripts $ chmod +x *.sh $ cd ~ $ mkdir -p k8s/http_scripts $ cp k8s_cluster_deploy/http_scripts/* k8s/http_scripts $ cd k8s_cluster_deploy/https_scripts $ chmod +x *.sh $ cd ~ $ mkdir -p k8s/https_scripts $ cp k8s_cluster_deploy/https_scripts/* k8s/http_scripts
2.4 安装 cfssl
- 本节同上一篇文章相同,熟悉的读者可以跳过
- 在 master1、master2 和 master3 上安装 cfssl
- 在左右 kubernetes 节点上安装 cfssl,执行 k8s/scripts/cfssl.sh 脚本,或者执行如下命令:
$ curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl $ curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson $ curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o /usr/local/bin/cfssl-certinfo $ chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson /usr/local/bin/cfssl-certinfo
- k8s/scripts/cfssl.sh 脚本内容如下:
$ cat k8s_cluster_deploy/scripts/cfssl.sh
curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl
curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson
curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o /usr/local/bin/cfssl-certinfo
chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson /usr/local/bin/cfssl-certinfo
2.5 安装 etcd
- 本节同上一篇文章相同,熟悉的读者可以跳过
- 在其中一台机器上(如 etcd01)创建目标文件夹
$ mkdir -p /opt/etcd/{cfg,bin,ssl}
- 下载 etcd 最新版安装包
$ wget https://github.com/etcd-io/etcd/releases/download/v3.3.18/etcd-v3.3.18-linux-amd64.tar.gz
$ tar -zxvf etcd-v3.3.18-linux-amd64.tar.gz
$ cp etcd-v3.3.18-linux-amd64/etcdctl etcd-v3.3.18-linux-amd64/etcd /opt/etcd/bin
- 创建文件夹 k8s/etcd-cert,其中 k8s 部署相关文件和脚本的存储根目录,etcd-cert 暂存 etcd https 的证书
$ mkdir -p k8s/etcd-cert
- 复制 etcd-cert.sh 脚本执行 etcd-cert 目录中
$ cp k8s/scripts/etcd-cert.sh k8s/etcd-cert
- 脚本内容如下:
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"www": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF
cat > ca-csr.json <<EOF
{
"CN": "etcd CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"ST": "Beijing"
}
]
}
EOF
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
#-----------------------
cat > server-csr.json <<EOF
{
"CN": "etcd",
"hosts": [
"127.0.0.1",
"192.168.1.65",
"192.168.1.66",
"192.168.1.67",
"192.168.1.68",
"192.168.1.69"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing"
}
]
}
EOF
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server
- 注意修改 server-csr.json 部分的 hosts 内容为 127.0.0.1 和虚拟机集群的所有 IP 地址
- 执行脚本
$ ./etcd-cert.sh
2020/02/20 17:18:09 [INFO] generating a new CA key and certificate from CSR
2020/02/20 17:18:09 [INFO] generate received request
2020/02/20 17:18:09 [INFO] received CSR
2020/02/20 17:18:09 [INFO] generating key: rsa-2048
2020/02/20 17:18:09 [INFO] encoded CSR
2020/02/20 17:18:09 [INFO] signed certificate with serial number 712703952401219579947544408367305212876133158662
2020/02/20 17:18:09 [INFO] generate received request
2020/02/20 17:18:09 [INFO] received CSR
2020/02/20 17:18:09 [INFO] generating key: rsa-2048
2020/02/20 17:18:09 [INFO] encoded CSR
2020/02/20 17:18:09 [INFO] signed certificate with serial number 59975233056205858127163767550140095337822886214
2020/02/20 17:18:09 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
- 拷贝证书
$ cp *.pem /opt/etcd/ssl
- 执行 k8s/scripts/etcd.sh 脚本,第一个参数为 etcd 节点名称,第二个为当前启动节点的 IP 地址,第三个参数为 Etcd 集群的所有地址
$ ./k8s/scripts/etcd.sh etcd01 192.168.1.67 etcd01=https://192.168.1.67:2380,etcd02=https://192.168.1.68:2380,etcd03=https://192.168.1.69:2380
- k8s/scripts/etcd.sh 脚本内容如下:
#!/bin/bash
# example: ./etcd.sh etcd01 192.168.1.10 etcd01=https://192.168.1.10:2380,etcd02=https://192.168.1.11:2380,etcd03=https://192.168.1.12:2380
ETCD_NAME=$1
ETCD_IP=$2
ETCD_CLUSTER=$3
systemctl stop etcd
systemctl disable etcd
WORK_DIR=/opt/etcd
cat <<EOF >$WORK_DIR/cfg/etcd
#[Member]
ETCD_NAME="${ETCD_NAME}"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://${ETCD_IP}:2380"
ETCD_LISTEN_CLIENT_URLS="https://${ETCD_IP}:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://${ETCD_IP}:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://${ETCD_IP}:2379"
ETCD_INITIAL_CLUSTER="${ETCD_CLUSTER}"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF
cat <<EOF >/usr/lib/systemd/system/etcd.service
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=${WORK_DIR}/cfg/etcd
ExecStart=${WORK_DIR}/bin/etcd
--name=${ETCD_NAME}
--data-dir=${ETCD_DATA_DIR}
--listen-peer-urls=${ETCD_LISTEN_PEER_URLS}
--listen-client-urls=${ETCD_LISTEN_CLIENT_URLS},http://127.0.0.1:2379
--advertise-client-urls=${ETCD_ADVERTISE_CLIENT_URLS}
--initial-advertise-peer-urls=${ETCD_INITIAL_ADVERTISE_PEER_URLS}
--initial-cluster=${ETCD_INITIAL_CLUSTER}
--initial-cluster-token=${ETCD_INITIAL_CLUSTER_TOKEN}
--initial-cluster-state=new
--cert-file=${WORK_DIR}/ssl/server.pem
--key-file=${WORK_DIR}/ssl/server-key.pem
--peer-cert-file=${WORK_DIR}/ssl/server.pem
--peer-key-file=${WORK_DIR}/ssl/server-key.pem
--trusted-ca-file=${WORK_DIR}/ssl/ca.pem
--peer-trusted-ca-file=${WORK_DIR}/ssl/ca.pem
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable etcd
systemctl restart etcd
- 接下来将 etcd 的工作目录和 etcd.service 文件复制给 etcd02 和 etcd03
$ scp -r /opt/etcd/ root@192.168.1.68:/opt/
$ scp -r /opt/etcd/ root@192.168.1.69:/opt/
$ scp /usr/lib/systemd/system/etcd.service root@192.168.1.68:/usr/lib/systemd/system/
$ scp /usr/lib/systemd/system/etcd.service root@192.168.1.69:/usr/lib/systemd/system/
- 分别在 etcd02 和 etcd03 上修改配置文件:/opt/etcd/cfg/etcd
[root@192.168.1.68] $ vim /opt/etcd/cfg/etcd
#[Member]
ETCD_NAME="etcd02"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.1.68:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.1.68:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.1.68:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.1.68:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.1.67:2380,etcd02=https://192.168.1.68:2380,etcd03=https://192.168.1.69
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
[root@192.168.1.69] $ vim /opt/etcd/cfg/etcd
#[Member]
ETCD_NAME="etcd03"
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_PEER_URLS="https://192.168.1.69:2380"
ETCD_LISTEN_CLIENT_URLS="https://192.168.1.69:2379"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="https://192.168.1.69:2380"
ETCD_ADVERTISE_CLIENT_URLS="https://192.168.1.69:2379"
ETCD_INITIAL_CLUSTER="etcd01=https://192.168.1.67:2380,etcd02=https://192.168.1.68:2380,etcd03=https://192.168.1.69
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
- 分别在 etcd02 和 etcd03 上启动 etcd 服务
$ sudo systemctl enable etcd.service
Created symlink /etc/systemd/system/multi-user.target.wants/etcd.service → /usr/lib/systemd/system/etcd.service.
$ sudo systemctl start etcd.service
- 检查安装是否成功,执行如下命令:
$ sudo etcdctl --ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.1.67:2379,https://192.168.1.68:2379,https://192.168.1.69:2379" cluster-health
member 3143a1397990e241 is healthy: got healthy result from https://192.168.1.68:2379
member 469e7b2757c25086 is healthy: got healthy result from https://192.168.1.67:2379
member 5b1e32d0ab5e3e1b is healthy: got healthy result from https://192.168.1.69:2379
cluster is healthy
2.6 部署 flannel
- 本节同上一篇文章相同,熟悉的读者可以跳过
- 在 node1、node2、node3 三个节点上分别部署 flannel
- 写入分配的子网段到 etcd 中,供 flannel 使用:
$ /opt/etcd/bin/etcdctl --ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --endpoints="https://127.0.0.1:2379" set /coreos.com/network/config '{ "Network": "172.17.0.0/16", "Backend": {"Type": "vxlan"}}'
{ "Network": "172.17.0.0/16", "Backend": {"Type": "vxlan"}}
- 查看写入的信息
$ /opt/etcd/bin/etcdctl --ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --endpoints="https://127.0.0.1:2379" get /coreos.com/network/config
{ "Network": "172.17.0.0/16", "Backend": {"Type": "vxlan"}}
- 下载 flannel 最新安装包
$ wget https://github.com/coreos/flannel/releases/download/v0.11.0/flannel-v0.11.0-linux-amd64.tar.gz
$ tar -zxvf flannel-v0.11.0-linux-amd64.tar.gz
$ mkdir -p /opt/kubernetes/{cfg,bin,ssl}
$ mv mk-docker-opts.sh flanneld /opt/kubernetes/bin/
- 执行脚本 k8s/scripts/flannel.sh,第一个参数为 etcd 地址
$ ./k8s/scripts/flannel.sh https://192.168.1.67:2379,https://192.168.1.68:2379,https://192.168.1.69:2379
- 脚本内容如下:
$ cat ./k8s/scripts/flannel.sh
#!/bin/bash
ETCD_ENDPOINTS=${1:-"http://127.0.0.1:2379"}
systemctl stop flanneld
systemctl disable flanneld
cat <<EOF >/opt/kubernetes/cfg/flanneld
FLANNEL_OPTIONS="--etcd-endpoints=${ETCD_ENDPOINTS} \
-etcd-cafile=/opt/etcd/ssl/ca.pem \
-etcd-certfile=/opt/etcd/ssl/server.pem \
-etcd-keyfile=/opt/etcd/ssl/server-key.pem"
EOF
cat <<EOF >/usr/lib/systemd/system/flanneld.service
[Unit]
Description=Flanneld overlay address etcd agent
After=network-online.target network.target
Before=docker.service
[Service]
Type=notify
EnvironmentFile=/opt/kubernetes/cfg/flanneld
ExecStart=/opt/kubernetes/bin/flanneld --ip-masq $FLANNEL_OPTIONS
ExecStartPost=/opt/kubernetes/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker -f /run/flannel/subnet.env
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable flanneld
systemctl restart flanneld
- 查看启动时指定的子网
$ cat /run/flannel/subnet.envFLANNEL_NETWORK=172.17.0.0/16
FLANNEL_SUBNET=172.17.89.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true
$ cat /run/flannel/docker
DOCKER_OPT_BIP="--bip=172.17.89.1/24"
DOCKER_OPT_IPMASQ="--ip-masq=false"
DOCKER_OPT_MTU="--mtu=1450"
DOCKER_OPTS=" --bip=172.17.89.1/24 --ip-masq=false --mtu=1450"
- 执行
vim /usr/lib/systemd/system/docker.service
修改 docker 配置
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
BindsTo=containerd.service
After=network-online.target firewalld.service containerd.service
Wants=network-online.target
Requires=docker.socket
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
EnvironmentFile=/run/flannel/docker
ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS -H unix:///var/run/docker.soc
#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.soc
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
......
- 重启 docker 服务
$ systemctl daemon-reload $ systemctl restart docker
- 查看 flannel 网络,docker0 位于 flannel 分配的子网中
$ ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.89.1 netmask 255.255.255.0 broadcast 172.17.89.255
ether 02:42:fb:16:3b:12 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255
inet6 fe80::a00:27ff:feaf:b59f prefixlen 64 scopeid 0x20<link>
ether 08:00:27:af:b5:9f txqueuelen 1000 (Ethernet)
RX packets 517 bytes 247169 (247.1 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 361 bytes 44217 (44.2 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.67 netmask 255.255.255.0 broadcast 192.168.1.255
inet6 fe80::a00:27ff:fe9f:cb5c prefixlen 64 scopeid 0x20<link>
inet6 2409:8a10:2e24:d130:a00:27ff:fe9f:cb5c prefixlen 64 scopeid 0x0<global>
ether 08:00:27:9f:cb:5c txqueuelen 1000 (Ethernet)
RX packets 9244 bytes 2349434 (2.3 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 7420 bytes 1047863 (1.0 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
flannel.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450
inet 172.17.89.0 netmask 255.255.255.255 broadcast 0.0.0.0
inet6 fe80::60c3:ecff:fe34:9d6c prefixlen 64 scopeid 0x20<link>
ether 62:c3:ec:34:9d:6c txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 6 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 3722 bytes 904859 (904.8 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3722 bytes 904859 (904.8 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- 创建容器,查看容器网络
[root@adf9fc37d171 /]# yum install -y net-tools
[root@adf9fc37d171 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.89.2 netmask 255.255.255.0 broadcast 172.17.89.255
ether 02:42:ac:11:59:02 txqueuelen 0 (Ethernet)
RX packets 1538 bytes 14149689 (13.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1383 bytes 81403 (79.4 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@adf9fc37d171 /]# ping 172.17.89.1
PING 172.17.89.1 (172.17.89.1) 56(84) bytes of data.
64 bytes from 172.17.89.1: icmp_seq=1 ttl=64 time=0.045 ms
64 bytes from 172.17.89.1: icmp_seq=2 ttl=64 time=0.045 ms
64 bytes from 172.17.89.1: icmp_seq=3 ttl=64 time=0.050 ms
64 bytes from 172.17.89.1: icmp_seq=4 ttl=64 time=0.052 ms
64 bytes from 172.17.89.1: icmp_seq=5 ttl=64 time=0.049 ms
- 测试可以 ping 通 docker0 网卡 证明 flannel 起到路由作用
2.7 安装 nginx
- 在 lb2 上安装 nginx,执行如下命令:
$ sudo apt-get -y install nginx
- 使用 k8s_cluster_deploy/nginx/nginx.conf 替换 /etc/nginx/nginx.conf
- k8s_cluster_deploy/nginx/nginx.conf 内容如下:
$ cat k8s_cluster_deploy/nginx/nginx.conf user www-data; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; worker_processes 2; worker_rlimit_nofile 65536; events { worker_connections 32768; } http { ## # Basic Settings ## sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; ## # SSL Settings ## ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; ## # Logging Settings ## access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; ## # Gzip Settings ## gzip on; # gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; ## # Virtual Host Configs ## log_format default '$remote_addr:$remote_port->$upstream_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } #mail { # # See sample authentication script at: # # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript # # # auth_http localhost/auth.php; # # pop3_capabilities "TOP" "USER"; # # imap_capabilities "IMAP4rev1" "UIDPLUS"; # # server { # listen localhost:110; # protocol pop3; # proxy on; # } # # server { # listen localhost:143; # protocol imap; # proxy on; # } #}
- 在配置中主要定义了日志格式,命名为 default
- 将 k8s_cluster_deploy/nginx/conf.d/k8s.conf,复制到 /etc/nginx/conf.d 中
- k8s_cluster_deploy/nginx/conf.d/k8s.conf 内容如下:
$ cat k8s_cluster_deploy/nginx/conf.d/k8s.conf upstream kubernetes-api-cluster-tls { server 192.168.1.67:6443 max_fails=0 fail_timeout=3s weight=1; server 192.168.1.68:6443 max_fails=0 fail_timeout=3s weight=1; # server 192.168.1.69:6443 weight=1 max_fails=0 fail_timeout=3s; } upstream kubernetes-api-cluster { server 192.168.1.67:8080 weight=100 max_fails=0 fail_timeout=3s; server 192.168.1.68:8080 weight=100 max_fails=0 fail_timeout=3s; # server 192.168.1.69:8080 weight=100 max_fails=0 fail_timeout=3s; } server { listen 8443 ssl; ssl_certificate /etc/nginx/ssl/master/kube-apiserver.pem; # kube-apiserver cert ssl_certificate_key /etc/nginx/ssl/master/kube-apiserver-key.pem; # kube-apiserver key ssl_trusted_certificate /etc/nginx/ssl/ca.pem; # ca.pem ssl_prefer_server_ciphers on; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS; location / { proxy_ssl_certificate /etc/nginx/ssl/test-user.pem; # kubectl cert proxy_ssl_certificate_key /etc/nginx/ssl/test-user-key.pem; # kubectl key proxy_ssl_trusted_certificate /etc/nginx/ssl/ca.pem; # ca.pem proxy_pass https://kubernetes-api-cluster-tls; proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_403 http_404 http_429 non_idempotent; proxy_next_upstream_timeout 1s; proxy_next_upstream_tries 3; proxy_set_header Host $host; proxy_set_header X-Real-Ip $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-NginX-Proxy true; proxy_read_timeout 600s; } access_log /var/log/nginx/access.log default; } server { listen 8081; location / { proxy_pass http://kubernetes-api-cluster; proxy_next_upstream error timeout http_500 http_502 http_503 http_504 http_403 http_429 non_idempotent; proxy_next_upstream_timeout 3s; proxy_next_upstream_tries 5; proxy_ignore_client_abort on; proxy_set_header Host $host; proxy_set_header X-Real-Ip $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-NginX-Proxy true; proxy_connect_timeout 300s; } #access_log /var/log/nginx/access.log default; }
- 配置中分别实现了监听 8443 和 8081 端口,8443 为 https 端口,8081 为 http 端口
- 8443 端口中 ssl_certificate、ssl_certificate_key 分配指定为 kube-apiserver 的服务端证书和私钥
- proxy_ssl_certificate 和 proxy_ssl_certificate_key 分别指定为一个具有 cluster-admin 权限的用户的客户端证书和私钥
- 当前由于证书和私钥还未生存,暂时不需要重启服务
2.8 脚本一键安装
- 上一篇中,我们详细介绍了各个组件的证书生成、配置、重启服务和验证
- 在本篇文章中为了方便部署,我们分别为 http 和 https 方式编写了一键安装脚本
- 进入相应的目录启动服务
$ cd k8s/http_scripts $ ./install.sh $ cd k8s/https_scripts $ ./install.sh
-
其中 k8s/https_scripts/install.sh 脚本内容如下:
$ cat k8s/https_scripts/install.sh #!/bin/bash sudo mkdir -p /opt/kubernetes/{bin,cfg,log,ssl} sudo rm -rf /opt/kubernetes/cfg/* sudo rm -rf /opt/kubernetes/log/* sudo rm -rf /opt/kubernetes/ssl/* ssh root@master2 "mkdir -p /opt/kubernetes/{bin,cfg,log} && rm -rf /opt/kubernetes/cfg/* && rm -rf /opt/kubernetes/log/* && rm -rf /opt/kubernetes/ssl/*" ssh root@master3 "mkdir -p /opt/kubernetes/{bin,cfg,log} && rm -rf /opt/kubernetes/cfg/* && rm -rf /opt/kubernetes/log/* && rm -rf /opt/kubernetes/ssl/*" mkdir -p ../k8s-cert sudo rm -rf ../k8s-cert/* sudo rm -rf /opt/kubernetes/ssl/* ssh root@master2 "rm -rf /opt/kubernetes/ssl/*" ssh root@master3 "rm -rf /opt/kubernetes/ssl/*" cp k8s-cert.sh ../k8s-cert cd ../k8s-cert ./k8s-cert.sh echo -e " 33[32m ======>>>>>>copy new cert 33[0m" sudo cp -r ca* admin* test-user* master node /opt/kubernetes/ssl sudo scp -r /opt/kubernetes/ssl root@master2:/opt/kubernetes/ sudo scp -r /opt/kubernetes/ssl root@master3:/opt/kubernetes/ cd ../https_scripts mkdir -p ../config sudo rm -rf ../config/* sudo rm -rf /opt/kubernetes/cfg/* ssh root@master2 "rm -rf /opt/kubernetes/cfg/*" ssh root@master3 "rm -rf /opt/kubernetes/cfg/*" cp config.sh ../config cd ../config sudo ./config.sh https://192.168.1.67:2379,https://192.168.1.68:2379,https://192.168.1.69:2379 192.168.1.66 192.168.1.67 /opt/kubernetes/ssl echo -e " 33[32m ======>>>>>>copy new config 33[0m" sudo cp * /opt/kubernetes/cfg sudo chown ao:ao config sudo chown ao:ao test-user.config cp config ~/.kube/ cp test-user.config ~/.kube/ sudo scp /opt/kubernetes/cfg/* root@master2:/opt/kubernetes/cfg/ scp config ao@master2:/home/ao/.kube/ sudo scp /opt/kubernetes/cfg/* root@master3:/opt/kubernetes/cfg/ scp config ao@master3:/home/ao/.kube/ cd ../https_scripts echo -e " 33[32m ======>>>>>>restart nginx 33[0m" ssh root@lb2 "systemctl stop nginx.service && systemctl disable nginx.service && rm /var/log/nginx/*" sudo scp -r /opt/kubernetes/ssl/* root@lb2:/etc/nginx/ssl/ ssh root@lb2 "cd /etc/nginx/ssl && cat admin.pem > test.pem && cat admin-key.pem > test-key.pem && systemctl stop haproxy.service && systemctl daemon-reload && systemctl restart nginx.service && systemctl status nginx.service" echo -e " 33[32m ======>>>>>>restart etcd 33[0m" sudo systemctl stop etcd.service ssh root@master2 "systemctl stop etcd.service" ssh root@master3 "systemctl stop etcd.service" sleep 5s sudo rm -rf /var/lib/etcd/default.etcd/member ssh root@master2 "rm -rf /var/lib/etcd/default.etcd/member" ssh root@master3 "rm -rf /var/lib/etcd/default.etcd/member" sleep 5s sudo systemctl daemon-reload sudo systemctl restart etcd.service ssh root@master2 "systemctl daemon-reload && systemctl restart etcd.service && systemctl status etcd.service" ssh root@master3 "systemctl daemon-reload && systemctl restart etcd.service && systemctl status etcd.service" sudo etcdctl --ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.1.67:2379,https://192.168.1.68,https://192.168.1.69" cluster-health sudo etcdctl --ca-file=/opt/etcd/ssl/ca.pem --cert-file=/opt/etcd/ssl/server.pem --key-file=/opt/etcd/ssl/server-key.pem --endpoints="https://192.168.1.67:2379,https://192.168.1.68,https://192.168.1.69" set /coreos.com/network/config '{ "Network": "172.17.0.0/16", "Backend": {"Type": "vxlan"}}' echo -e " 33[32m ======>>>>>>restart flannel && docker 33[0m" sudo ./flannel.sh https://192.168.1.67:2379,https://192.168.1.68:2379,https://192.168.1.69:2379 scp flannel.sh ao@master2:/home/ao/Coding/k8s/scripts && scp flannel.sh ao@master3:/home/ao/Coding/k8s/scripts sudo systemctl daemon-reload sudo systemctl restart docker ssh root@master2 "hostname && cd /home/ao/Coding/k8s/scripts && ./flannel.sh https://192.168.1.67:2379,https://192.168.1.68:2379,https://192.168.1.69:2379 && systemctl daemon-reload && systemctl restart docker && systemctl status docker" ssh root@master3 "hostname && cd /home/ao/Coding/k8s/scripts && ./flannel.sh https://192.168.1.67:2379,https://192.168.1.68:2379,https://192.168.1.69:2379 && systemctl daemon-reload && systemctl restart docker && systemctl status docker" echo -e " 33[32m ======>>>>>>restart kube-apiserver 33[0m" sudo systemctl stop kube-apiserver ssh root@master2 systemctl stop kube-apiserver ssh root@master3 systemctl stop kube-apiserver sudo ./apiserver.sh 192.168.1.67 https://192.168.1.67:2379,https://192.168.1.68:2379,https://192.168.1.69:2379 scp apiserver.sh ao@master2:/home/ao/Coding/k8s/https_scripts && scp apiserver.sh ao@master3:/home/ao/Coding/k8s/https_scripts ssh root@master2 "hostname && cd /home/ao/Coding/k8s/https_scripts && ./apiserver.sh 192.168.1.68 https://192.168.1.67:2379,https://192.168.1.68:2379,https://192.168.1.69:2379" ssh root@master3 "hostname && cd /home/ao/Coding/k8s/https_scripts && ./apiserver.sh 192.168.1.69 https://192.168.1.67:2379,https://192.168.1.68:2379,https://192.168.1.69:2379" echo -e " 33[32m ======>>>>>>restart kube-controller-manager 33[0m" sudo systemctl stop kube-controller-manager ssh root@master2 systemctl stop kube-controller-manager ssh root@master3 systemctl stop kube-controller-manager sudo ./controller-manager.sh scp controller-manager.sh ao@master2:/home/ao/Coding/k8s/https_scripts && scp controller-manager.sh ao@master3:/home/ao/Coding/k8s/https_scripts ssh root@master2 "hostname && cd /home/ao/Coding/k8s/https_scripts && ./controller-manager.sh" ssh root@master3 "hostname && cd /home/ao/Coding/k8s/https_scripts && ./controller-manager.sh" echo -e " 33[32m ======>>>>>>restart kube-scheduler 33[0m" sudo systemctl stop kube-scheduler ssh root@master2 systemctl stop kube-scheduler ssh root@master3 systemctl stop kube-scheduler sudo ./scheduler.sh scp scheduler.sh ao@master2:/home/ao/Coding/k8s/https_scripts && scp scheduler.sh ao@master3:/home/ao/Coding/k8s/https_scripts ssh root@master2 "hostname && cd /home/ao/Coding/k8s/https_scripts && ./scheduler.sh" ssh root@master3 "hostname && cd /home/ao/Coding/k8s/https_scripts && ./scheduler.sh" echo -e " 33[32m ======>>>>>>restart kubelet 33[0m" sudo systemctl stop kubelet ssh root@master2 systemctl stop kubelet ssh root@master3 systemctl stop kubelet sudo ./kubelet.sh 192.168.1.67 node1 scp kubelet.sh ao@master2:/home/ao/Coding/k8s/https_scripts && scp kubelet.sh ao@master3:/home/ao/Coding/k8s/https_scripts ssh root@master2 "hostname && cd /home/ao/Coding/k8s/https_scripts && ./kubelet.sh 192.168.1.68 node2" ssh root@master3 "hostname && cd /home/ao/Coding/k8s/https_scripts && ./kubelet.sh 192.168.1.69 node3" echo -e " 33[32m ======>>>>>>restart proxy 33[0m" sudo systemctl stop kube-proxy ssh root@master2 systemctl stop kube-proxy ssh root@master3 systemctl stop kube-proxy sudo ./proxy.sh node1 scp proxy.sh ao@master2:/home/ao/Coding/k8s/https_scripts && scp proxy.sh ao@master3:/home/ao/Coding/k8s/https_scripts ssh root@master2 "hostname && cd /home/ao/Coding/k8s/https_scripts && ./proxy.sh node2" ssh root@master3 "hostname && cd /home/ao/Coding/k8s/https_scripts && ./proxy.sh node3" kubectl delete -f ../yamls/jobs-tester.yaml kubectl delete clusterrolebinding jobs-test kubectl delete clusterrolebinding test-cluster-admin-binding kubectl apply -f ../yamls/jobs-tester.yaml kubectl create clusterrolebinding jobs-test --clusterrole=jobs-tester --user=test-user kubectl create clusterrolebinding test-cluster-admin-binding --clusterrole=cluster-admin --user=test-user echo "1st" sleep 10s kubectl label node node1 node2 node3 node-role.kubernetes.io/master=true echo "2nd" kubectl get nodes --all-namespaces kubectl taint nodes --all node-role.kubernetes.io/master=true:NoSchedule kubectl taint nodes --all node-role.kubernetes.io/master- sleep 10s echo "3rd" kubectl get nodes --all-namespaces kubectl delete -f ../yamls/nginx-deployment.yaml sleep 5s kubectl apply -f ../yamls/nginx-deployment.yaml kubectl get pods --all-namespaces
- 上述脚本中需要各个节点的 /etc/hosts 中配置实验环境中的节点名称和 IP 地址的对应关系
- 脚本包括清空 etcd、复制证书私钥给 nginx 并重启服务、创建 nginx-deployment 作为测试等步骤
- 其中脚本创建了一个名叫 test-user 赋予 cluser-admin 权限配置
- 配置 kube-controller-manager、kube-scheduler 的 kubeconfig 文件中的客户端证书和私钥为 test-user 用户的,用于后续的负载均衡配置
3. 小结
- 后续文章会讲解 nginx 的负载均衡相关配置
- 上述的脚本均上传至 github 仓库
- 欢迎各位提出问题和批评