k8s-kubeasz-阿里云vpc部署记录

Posted by     "李森" on Thursday, September 27, 2018

TOC

  1. 这是本人参照开源项目kubeasz(项目地址),在阿里云vpc环境使用slb搭建的一套3*master+3*node的高可用k8s集群,这并不是一份完整的k8s安装文档,这里只是记录使用kubeasz搭建集群关键步骤以及需要注意的点,完整的请参考源项目,命令操作时建议使用screen进行操作,以免网络问题造成操作失败。

  2. 这里说明下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

  1. 因为阿里云的slb 是不支持后端rs访问slb地址,用kubeasz项目部署时,slb后面的master是需要跟slb通信,这里用一台haproxy中转下,考虑高可用也可以用用两台。

  2. 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