TOC
这是本人参照开源项目kubeasz(项目地址),在阿里云vpc环境使用slb搭建的一套3*master+3*node的高可用k8s集群,这并不是一份完整的k8s安装文档,这里只是记录使用kubeasz搭建集群关键步骤以及需要注意的点,完整的请参考源项目,命令操作时建议使用screen进行操作,以免网络问题造成操作失败。
这里说明下master高可用网络通信:多master使用slb是为了解决api-server的高可用,api-server是为master外部相关应用(kubectl、kubelet等)服务的,master上的cm、scheduler其实是只跟本机的api-server(监听地址一般为127.0.0.1/内网ip)通信,跟slb没有通信需求,并且多master中通过内部ip通信竞选只有一个cm和scheduler是生效可用,其他的节点为备用。
关于阿里云slb
因为阿里云的slb 是不支持后端rs访问slb地址,用kubeasz项目部署时,slb后面的master是需要跟slb通信,这里用一台haproxy中转下,考虑高可用也可以用用两台。
kubeasz 新版本将master node角色重合,基于上述master高可用网络通信,就算有slb,还是得需要haproxy了,如果master可以去掉node角色,haproxy只需要在部署的时候使用下,部署完可以直接去掉,让slb直连master (这样会造成master就无法使用kubectl), 原理上将是没问题的,只是影不影响kubeasz后续的周边服务安装就不得而知,我这没做测试。
服务器规划
hostname | ip | 配置 | 用途 |
---|---|---|---|
k8s-lb01 | 172.16.68.13 | 2c4g 60g+60g | lb |
k8s-deploy01 | 172.16.68.12 | 2c4g 60g+60g | 跳板、发布、备份 |
k8s-master01 | 172.16.68.11 | 4c8g 60g+60g | master/etcd |
k8s-master02 | 172.16.68.10 | 4c8g 60g+60g | master/etcd |
k8s-master03 | 172.16.68.9 | 4c8g 60g+60g | master/etcd |
k8s-ndoe01 | 172.16.68.8 | 4c8g 60g+60g | node |
k8s-ndoe02 | 172.16.68.7 | 4c8g 60g+60g | node |
k8s-ndoe03 | 172.16.68.6 | 4c8g 60g+60g | node |
阿里云slb
名称 | ip | 备注 |
---|---|---|
by-master | 172.16.68.14 | kube-apiserver高可用 |
组件说明
组件 | 版本 |
---|---|
os | CentOS Linux release 7.4.1708 (Core) |
kernel | 4.18.11-1.el7.elrepo.x86_64(自行升级) |
k8s | v1.11.3 |
etcd | v3.3.8 |
docker | 17.03.2-ce |
network | calico v3.1.3 |
建议大家把内核都升级到最新的lt版本,不然会出现各种bug,因为centos的内核版本实在太老了,我这里用的ml版本。
安装准备
各节点安装python
# 文档中脚本默认均以root用户执行
# 安装 epel 源并更新
yum install epel-release -y
yum update
# 安装python
yum install python -y
各节点时间同步
集群时间不同步会造成后续很多问题(譬如etcd不可用),这是集群基本条件;阿里云ecs时间同步ntp服务默认装好,这里就省略,没有的自行安装。
初始配置
- 配置hostname
- 挂载数据盘
分享一个硬盘挂载的小脚本
cat fdisk.sh
#!/bin/bash
###FORMAT DISK###
###by lisen###
DISK=/dev/vdb
DIR=/opt
echo -e "\033[31mWarning!Ready mount $DISK...\033[0m"
read -p "Please input your choice:yes|no,if you want exit,please input no:" ANS
until [ $ANS == 'yes' ]; do
echo "Quiting...goodbye!" && exit 7
read -p "Please input your choice:yes|no,if you want exit,please input no:" ANS
done
if fdisk -l | grep $DISK &> /dev/null; then
echo "$DISK was found!!!disk partitioning..."
mkdir -p $DIR && echo "$DIR created!!!!"
echo 'n
p
1
w'|fdisk $DISK &> /dev/null
partprobe $DISK
sync
echo "Partition parttables success!!!"
sleep 2
echo "Fomat $DISK!!!!!"
mkfs.xfs ${DISK}1 &> /dev/null || echo "$DISK fomat success!"
echo "Add parttables to /etc/fstab"
echo "${DISK}1 $DIR xfs defaults 0 0" >> /etc/fstab && mount -a &> /dev/null && echo "Well done!"
df -h
mount
else
echo "$DISK not exist!!"
exit 8
fi
- 升级内核
自己根据情况自行解决,贴下centos参考。
# 参考 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm yum --disablerepo=\* --enablerepo=elrepo-kernel repolist yum --disablerepo=\* --enablerepo=elrepo-kernel list kernel* yum --disablerepo=\* --enablerepo=elrepo-kernel install -y kernel-ml.x86_64 uname -a awk -F\' '$1=="menuentry " {print $2}' /etc/grub2.cfg grub2-set-default 0 reboot rpm -qa|grep kernel|grep 3.10|xargs yum remove -y yum --disablerepo=\* --enablerepo=elrepo-kernel install -y kernel-ml-tools.x86_64 rpm -qa|grep kernel reboot 至此内核升级完毕!
在deploy节点安装及准备ansible
yum install git python-pip -y
# pip安装ansible(国内如果安装太慢可以直接用pip阿里云加速)
pip install pip --upgrade -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
pip install --no-cache-dir ansible -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
# pip install pip --upgrade
# pip install ansible
在deploy节点配置免密码登陆
ssh-keygen -t rsa -b 2048 -C "deploy@123.com" -P ''
for i in 172.16.68.{6..13}; do ssh-copy-id $i; done
#ssh-copy-id $IPs #$IPs为所有节点地址包括自身,按照提示输入yes 和root密码
kubeasz配置
默认在deploy节点进行操作
下载源码解压到同样目录
git clone https://github.com/gjmzj/kubeasz.git
mkdir -p /etc/ansible
mv kubeasz/* /etc/ansible
下载二进制文件
请从分享的百度云链接,下载解压到/etc/ansible/bin目录,如果你有合适网络环境也可以按照/down/download.sh自行从官网下载各种tar包
tar xf /root/k8sfile/k8s.1-11-3.tar.gz -C /etc/ansible/
[可选] 下载离线docker镜像
服务器使用内部yum源/apt源,但是无法访问公网情况下,请下载离线docker镜像完成集群安装;从百度云盘把basic_images_kubeasz_x.y.tar.gz
下载解压到/etc/ansible/down
目录
tar xf /root/k8sfile/basic_images_kubeasz_0.3.tar.gz -C /etc/ansible/down/
配置集群参数
cd /etc/ansible
cp example/hosts.m-masters.example hosts
vim hosts # 根据实际情况修改此hosts文件
[root@k8s-deploy01 ~]# cat /etc/ansible/hosts
# 集群部署节点:一般为运行ansible 脚本的节点
# 变量 NTP_ENABLED (=yes/no) 设置集群是否安装 chrony 时间同步
[deploy]
172.16.68.12 NTP_ENABLED=no
# etcd集群请提供如下NODE_NAME,注意etcd集群必须是1,3,5,7...奇数个节点
[etcd]
172.16.68.11 NODE_NAME=etcd1
172.16.68.10 NODE_NAME=etcd2
172.16.68.9 NODE_NAME=etcd3
[kube-master]
172.16.68.11
172.16.68.10
172.16.68.9
# 负载均衡(目前已支持多于2节点,一般2节点就够了) 安装 haproxy+keepalived
[lb]
[haproxy]
172.16.68.13
[kube-node]
172.16.68.8
172.16.68.7
172.16.68.6
[kube-cluster:children]
kube-node
kube-master
# 参数 NEW_INSTALL:yes表示新建,no表示使用已有harbor服务器
[harbor]
172.16.68.12 HARBOR_DOMAIN="harbor.weimeng-hosp.com" NEW_INSTALL=yes
# 预留组,后续添加master节点使用
[new-master]
#192.168.1.5
# 预留组,后续添加node节点使用
[new-node]
#192.168.1.xx
[all:vars]
# ---------集群主要参数---------------
#集群部署模式:allinone, single-master, multi-master
DEPLOY_MODE=multi-master
#集群主版本号,目前支持: v1.8, v1.9, v1.10,v1.11
K8S_VER="v1.11"
# 集群 MASTER IP即 LB节点VIP地址,为区别与默认apiserver端口,设置VIP监听的服务端口8443
# 公有云上请使用云负载均衡内网地址和监听端口
MASTER_IP="172.16.68.14"
KUBE_APISERVER="https://{{ MASTER_IP }}:8443"
# 集群网络插件,目前支持calico, flannel, kube-router, cilium
CLUSTER_NETWORK="calico"
# 服务网段 (Service CIDR),注意不要与内网已有网段冲突
SERVICE_CIDR="10.69.0.0/16"
# POD 网段 (Cluster CIDR),注意不要与内网已有网段冲突
CLUSTER_CIDR="172.21.0.0/16"
# 服务端口范围 (NodePort Range)
NODE_PORT_RANGE="20000-40000"
# kubernetes 服务 IP (预分配,一般是 SERVICE_CIDR 中第一个IP)
CLUSTER_KUBERNETES_SVC_IP="10.69.0.1"
# 集群 DNS 服务 IP (从 SERVICE_CIDR 中预分配)
CLUSTER_DNS_SVC_IP="10.69.0.2"
# 集群 DNS 域名
CLUSTER_DNS_DOMAIN="cluster.local."
# 集群basic auth 使用的用户名和密码
BASIC_AUTH_USER="admin"
BASIC_AUTH_PASS="Weimeng@2018"
# ---------附加参数--------------------
#默认二进制文件目录
bin_dir="/opt/kube/bin"
#证书目录
ca_dir="/etc/kubernetes/ssl"
#部署目录,即 ansible 工作目录,建议不要修改
base_dir="/etc/ansible"
我这里根据自己的需求新增了下haproxy、kube-cluster
验证ansible安装,正常能看到每个节点返回 SUCCESS
ansible all -m ping
配置hosts文件、ssh-key
为了后续部署方便,建议还是配置好/etc/hosts文件、ssh-key,分发都所有节点。
vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.68.13 k8s-lb01
172.16.68.12 k8s-deploy01
172.16.68.11 k8s-master01
172.16.68.10 k8s-master02
172.16.68.9 k8s-master03
172.16.68.8 k8s-node01
172.16.68.7 k8s-node02
172.16.68.6 k8s-node03
ansible all -m copy -a 'src=/root/.ssh/authorized_keys dest=/root/.ssh/authorized_keys'
ansible all -m copy -a 'src=/etc/hosts dest=/etc/hosts'
ansible all -m copy -a 'src=/root/fdisk.sh dest=/root/'
开始安装k8s
如果你对集群安装流程不熟悉,请阅读项目首页 安装步骤 讲解后分步安装,并对 每步都进行验证
prepare
cd /etc/ansible/
# 注释epel安装,ecs默认自带
vim /etc/ansible/roles/prepare/tasks/centos.yml
#- name: 添加EPEL仓库
# yum: name=epel-release state=latest
ansible-playbook 01.prepare.yml
etcd
ansible-playbook 02.etcd.yml
# 验证etcd状态:
ssh k8s-master01
export NODE_IPS="172.16.68.10 172.16.68.11 172.16.68.9"
for ip in ${NODE_IPS}; do
ETCDCTL_API=3 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
https://172.16.68.10:2379 is healthy: successfully committed proposal: took = 1.629536ms
https://172.16.68.11:2379 is healthy: successfully committed proposal: took = 1.613388ms
https://172.16.68.9:2379 is healthy: successfully committed proposal: took = 1.80531ms
docker
# 更改docker服务存储路径:
ansible kube-cluster -a 'mkdir -p /opt/docker'
vim /etc/ansible/roles/docker/defaults/main.yml
# docker容器存储目录
STORAGE_DIR: "/opt/docker"
ansible-playbook 03.docker.yml
master
# 得先配置好slb+haproxy 不然会报错
ssh k8s-lb01 / ssh k8s-deploy01(不启动仅作为k8s-lb01备用节点)
yum install haproxy -y
vim /etc/haproxy/haproxy.cfg
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
nbproc 1
defaults
log global
timeout connect 5000
timeout client 10m
timeout server 10m
listen kube-master
bind 0.0.0.0:6443
mode tcp
option tcplog
balance source
server k8s-master01 172.16.68.11:6443 check inter 2000 fall 2 rise 2 weight 1
server k8s-master02 172.16.68.10:6443 check inter 2000 fall 2 rise 2 weight 1
server k8s-master03 172.16.68.9:6443 check inter 2000 fall 2 rise 2 weight 1
systemctl start haproxy
systemctl enable haproxy
vim /etc/ansible/roles/kube-node/defaults/main.yml
# 默认使用kube-proxy的 'iptables' 模式,可选 'ipvs' 模式(experimental)
PROXY_MODE: "ipvs"
# Kubelet 根目录
KUBELET_ROOT_DIR: "/opt/kubelet"
# node节点最大pod 数,大家根据实际情况更改
MAX_PODS: 30
# 增加kubelet 参数 对node节点进行资源限制,大家根据实际情况更改
vim /etc/ansible/roles/kube-node/templates/kubelet.service.j2
--authentication-token-webhook \
--authorization-mode=Webhook \
--cgroup-driver=cgroupfs \
--kube-reserved=cpu=500m,memory=1Gi,ephemeral-storage=10Gi \
--system-reserved=cpu=1,memory=1Gi,ephemeral-storage=10Gi \
--eviction-hard=memory.available<1Gi,nodefs.available<10% \
ansible kube-cluster -a 'mkdir -p /opt/kubelet'
ansible-playbook 04.kube-master.yml
kubectl cluster-info
kubectl get componentstatuses -o wide
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-1 Healthy {"health":"true"}
etcd-0 Healthy {"health":"true"}
etcd-2 Healthy {"health":"true"}
node
ansible-playbook 05.kube-node.yml
iptables清理:
iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat
network
# calico metrics 开启
vim /etc/ansible/roles/calico/templates/calico.yaml.j2
...
image: calico/node:v3.0.6
ports:
- containerPort: 9091
hostPort: 9091
name: http-metrics
...
# Disable IPv6 on Kubernetes.
- name: FELIX_IPV6SUPPORT
value: "false"
- name: FELIX_PROMETHEUSMETRICSENABLED
value: "true"
- name: FELIX_PROMETHEUSMETRICSPORT
value: "9091"
...
# svc (promethues-operator需要,如不使用可以不加,也可以后期部署promethues-operator再加)
apiVersion: v1
kind: Service
metadata:
namespace: kube-system
name: calico
labels:
k8s-app: calico-node
spec:
type: ClusterIP
clusterIP: None
ports:
- name: http-metrics
port: 9091
targetPort: 9091
protocol: TCP
selector:
k8s-app: calico-node
ansible-playbook 06.network.yml
calicoctl node status
# 查看所有calico相关数据
ETCDCTL_API=3 etcdctl --endpoints="http://127.0.0.1:2379" get --prefix /calico
# 查看 calico网络为各节点分配的网段
ETCDCTL_API=3 etcdctl --endpoints="http://127.0.0.1:2379" get --prefix /calico/ipam/v2/host
插件
# 根据实际情况安装
vim /etc/ansible/roles/cluster-addon/defaults/main.yml
ansible-playbook 07.cluster-addon.yml
一步安装
ansible-playbook 90.setup.yml
- [可选]对集群所有节点进行操作系统层面的安全加固
ansible-playbook roles/os-harden/os-harden.yml
,详情请参考os-harden项目
验证集群功能
查看集群状态
kubectl get node
kubectl cluster-info
kubectl top node
kubectl get ep --all-namespaces -o yaml
创建测试文件
cat > nginx-ds.yml <<EOF
apiVersion: v1
kind: Service
metadata:
name: nginx-ds
labels:
app: nginx-ds
spec:
type: NodePort
selector:
app: nginx-ds
ports:
- name: http
port: 80
targetPort: 80
---
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: nginx-ds
labels:
addonmanager.kubernetes.io/mode: Reconcile
spec:
template:
metadata:
labels:
app: nginx-ds
spec:
containers:
- name: my-nginx
image: nginx:1.7.9
ports:
- containerPort: 80
EOF
kubectl create -f nginx-ds.yml
kubectl get pods -o wide|grep nginx-ds
kubectl get svc -o wide|grep nginx-ds
# 检查nodeport可用性
curl k8s-node01:22462
# 出现nginx欢迎页
验证coredns
kubectl exec -it nginx-ds-8sd6z /bin/bash
cat /etc/resolv.conf
ping nginx-ds
# 能成功解析服务到ip证明dns正常
验证dashboard
# kube-apiserver 访问 dashboard
kubectl cluster-info
# 也可以通过nodeport 访问
kubectl get svc -n kube-system
# 创建登录 Dashboard 的 token 和 kubeconfig 配置文件
# 上面提到,Dashboard 默认只支持 token 认证,所以如果使用 KubeConfig 文件,需要在该文件中指定 token,不支持使用 client 证书认证。
# 创建登录 token
kubectl create sa dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
ADMIN_SECRET=$(kubectl get secrets -n kube-system | grep dashboard-admin | awk '{print $1}')
DASHBOARD_LOGIN_TOKEN=$(kubectl describe secret -n kube-system ${ADMIN_SECRET} | grep -E '^token' | awk '{print $2}')
echo ${DASHBOARD_LOGIN_TOKEN}
# 创建使用 token 的 KubeConfig 文件
# 设置集群参数
kubectl config set-cluster kubernetes \
--certificate-authority=/etc/kubernetes/ssl/ca.pem \
--embed-certs=true \
--server=https://172.16.68.14:8443 \
--kubeconfig=dashboard.kubeconfig
# 设置客户端认证参数,使用上面创建的 Token
kubectl config set-credentials dashboard_user \
--token=${DASHBOARD_LOGIN_TOKEN} \
--kubeconfig=dashboard.kubeconfig
# 设置上下文参数
kubectl config set-context default \
--cluster=kubernetes \
--user=dashboard_user \
--kubeconfig=dashboard.kubeconfig
# 设置默认上下文
kubectl config use-context default --kubeconfig=dashboard.kubeconfig
用生成的 dashboard.kubeconfig 登录 Dashboard。
harbor
harbor 还是建议使用helm部署的高可用harbor,详见blog文档k8s部署高可用harbor
docker-compose 配置参考:
# 我本地访问不了,翻墙解决
wget https://storage.googleapis.com/harbor-releases/release-1.6.0/harbor-offline-installer-v1.6.0.tgz
vim /etc/ansible/roles/harbor/defaults/main.yml
# harbor version
HARBOR_VER: "v1.6.0"
mkdir -p /opt/harbor/data
# 根据实际情况调整
vim /etc/ansible/roles/harbor/templates/harbor.cfg.j2
# 调整harbor存储路径
sed -i 's#/data#/opt/data#g' /etc/ansible/roles/harbor/tasks/main.yml
ansible-playbook 11.harbor.yml