本文编写于 160 天前,最后修改于 160 天前,其中某些信息可能已经过时。

部署k8s分布式

主机配置:

虚拟机方案:
  1. 使用虚拟机部署3个一样的centos7或者ubuntu虚拟机
  2. 配置2张网卡

    • 一张用来主机和虚拟机通讯(host only 网卡),master和node节点通信也是使用这张网卡
    • 一张用来nat和外网通信
三台物理机方案:
  1. 三台内网的主机即可,centos7或者ubuntu

配置docker的代理(主要用来拉取镜像使用)

mkdir -p /etc/systemd/system/docker.service.d

cat <<EOF >/etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://192.168.56.1:1087/"
Environment="HTTPS_PROXY=http://192.168.56.1:1087/"
Environment="NO_PROXY=localhost,127.0.0.1,localaddress,.localdomain.com"
EOF

systemctl daemon-reload
systemctl restart docker
  • 测试配置

    docker info | grep Proxy  # 有输出说明配置成功
    docker pull gcr.io/google-containers/hello-world # pull 成功代表代理器工作正常。
  • 也可以使用以下脚本去实现不代理就拉镜像

    kubernetes_version=1.13.0 #指定k8s版本
    for i in `kubeadm config images list --kubernetes-version=${kubernetes_version}`; do
      imageName=${i#k8s.gcr.io/}
      docker pull registry.aliyuncs.com/google_containers/$imageName
      docker tag registry.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
      docker rmi registry.aliyuncs.com/google_containers/$imageName
    done;

配置终端代理(如果有需要)

全局终端http/https代理:
cat <<EOF >>/etc/environment
http_proxy="http://{http代理地址}:8118/"
https_proxy="http://{http代理地址}:8118/"
no_proxy="localhost, 127.0.0.1"
EOF
source /etc/environment
仅限当前shell生效的代理(使用export):
export http_proxy="http://{http代理地址}:8118/"
export https_proxy="http://{http代理地址}:8118/"
export no_proxy="localhost, 127.0.0.1"

修改host.conf文件

修改这个文件的目的在于使用主机名都能访问,不需要输入ip地址

  • 三台机都要设置
#192.168.56.101 yeweinode1
# /etc/hosts
{节点1的ip} 节点1的主机名
{节点2的ip} 节点1的主机名
{节点3的ip} 节点1的主机名

设置防火墙

systemctl disable firewalld.service
systemctl stop firewall

yum install -y iptables-services && systemctl start iptables && systemctl enable iptables 
cat <<EOF > /etc/sysconfig/iptables
*filter
:INPUT ACCEPT [1:40]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1:140]
COMMIT
EOF

关闭selinux

# 临时禁用
setenforce 0

# 永久禁用 
vim /etc/selinux/config    # 或者修改/etc/sysconfig/selinux
SELINUX=disabled

打开nf-bridge模块

编辑/etc/sysctl.conf文件

net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_nonlocal_bind = 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_instances=8192
fs.inotify.max_user_watches=1048576
fs.file-max=52706963
fs.nr_open=52706963
net.ipv6.conf.all.disable_ipv6=1
net.netfilter.nf_conntrack_max=2310720
kernel.core_pattern = /data/cores/core-%e-%p-%t

然后sysctl -p生效

关闭swap

# 临时关闭
swapoff -a

# 注释掉以下字段
/dev/mapper/cl-swap     swap                    swap    defaults        0 0
如果不想关闭swap的话,需要做以下操作:
  1. kubeadm 启动时候需要加入参数

    --ignore-preflight-errors=swap
  2. 修改 /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
  3. 在这个文件加入以下代码:

    Environment="KUBELET_EXTRA_ARGS=--fail-swap-on=false"

使得最后看起来像这样:

命令行程序安装(安装kubectl kubeadm kubelet三个组件):

使用centos:
  • 配置软件源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
  • 安装kubelet kubeadm kubectl
yum install -y kubelet-1.13.0 kubeadm-1.13.0 kubectl-1.13.0 kubernetes-cni-0.6.0-0
systemctl enable kubelet && systemctl start kubelet
使用ubuntu:
apt-get update && apt-get install -y apt-transport-https
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add - 
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF  
apt-get update
apt-get install -y kubelet kubeadm kubectl

使用kubeadm启动k8s

使用ipvs模式,安装ipvs相关组件
//1、加载netfilter模块
modprobe br_netfilter  

//2、添加配置文件

cat  >  /etc/sysconfig/modules/ipvs.modules  <<EOF
#!/bin/bash
modprobe  --  ip_vs
modprobe  --  ip_vs_rr
modprobe  --  ip_vs_wrr
modprobe  --  ip_vs_sh
modprobe  --  nf_conntrack_ipv4
EOF

//3、赋予权限并引导
chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules &&lsmod | grep -e ip_vs -e nf_conntrack_ipv4
  • 在node1(master)中执行
kubeadm init --apiserver-advertise-address={这里填写node1的host-only网卡的地址} --pod-network-cidr=10.244.0.0/16 --ignore-preflight-errors=swap --kubernetes-version=1.12.7
#--apiserver-advertise-address 这个参数是k8s集群中master对外能访问的地址
#--pod-network-cidr=10.244.0.0/16 这一节是配置pod的内网网段
#--ignore-preflight-errors=swap 如果是使用swap启动的话,需要加这个参数

#或者使用下面的配置文件
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
  - system:bootstrappers:kubeadm:default-node-token
  token: abcdef.0123456789abcdef
  ttl: 24h0m0s
  usages:
  - signing
  - authentication
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 10.250.101.110 #修改为自己的ip
  bindPort: 6443
nodeRegistration:
  criSocket: /var/run/dockershim.sock
  name: k8s-master01-109.244.52.110
  taints:
  - effect: NoSchedule
    key: node-role.kubernetes.io/master
---
apiServer:
  timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: "k8s-vip:6444"  #高可用ip
controllerManager: {}
dns:
  type: CoreDNS
etcd:
  local:
    dataDir: /var/lib/etcd
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: v1.16.3 #修改版本
networking:
  dnsDomain: cluster.local
  podSubnet: 10.244.0.0/16 #修改flannel网段,也就是pod的网段,保持默认,测试修改会失败
  serviceSubnet: 10.96.0.0/16 #service 网段
scheduler: {}
---  #添加默认调度方式为ipvs
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
featureGates:
  SupportIPVSProxyMode: true
mode: ipvs 
  1. --apiserver-advertise-address=192.168.56.101 绑定 apiserver 到 master 节点的 Host-Only 适配器的地址,默认是绑到 NAT 的地址上,这样其他机器是永远也访问不到的。
  2. --pod-network-cidr=10.244.0.0/16 指定 pod 网络地址空间,我们使用 flannel 组件必须使用这个空间

    • 等待node1执行结束,会有以下的输出:

  • 如果你忘记了join的命令,可以使用如下命令重新生成一个

kubeadm token create --print-join-command

配置kubectl,使得能连上k8s的apiserver

这时候需要使用kubectl接入kubernets的api,在我们刚刚的kubeadm init时候,程序已经为我们创建了kubectl的配置文件,这时候我们只需要export到环境变量即可

1.如果是root用户的话
# root user
export KUBECONFIG=/etc/kubernetes/admin.conf

2.如果是非root用户的话
# non-root user
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

3.如果从其他机器操作的话
# 从本地主机操作,需要在本地安装 kubectl 客户端
mkdir -p ~/.kube
scp <username>@{远端服务器}:/home/<username>/.kube/config ~/.kube/config # 从 master 复制配置文件到本地
#把远端服务器的admin.conf拷贝到本地

以上的操作其实是把kubectl需要用到的配置文件配置到kubectl的配置当中

当完成了以上操作后,kuberctl已经能使用了

  • 在终端输入:
kubectl cluster-info
  • 会有类似下面的输出:

这时候kubectl命令是已经能正常连上api server,集群也处于可用状态

安装flannel网络

  • 可以通过修改kube-flannel.yml文件去修改flannel的默认监听端口
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

给 /opt/bin/flanneld 命令添加 --iface="br0" 参数 
#按照实际情况进行配置(一般情况下不需要)

kubectl apply -f kube-flannel.yml
  • 测试配置
kubectl get pods --all-namespaces -o wide 
# 稍等一会,下载镜像需要一定时间,
#最后应该显示 flannel pods 是 Running 状态, kube-dns 也是 Running 状态

​ 如图:

  • 如果出现coredns多次启动失败,可能是resolver被systemd取代了,因此要么禁用systemd的reslover,要么加入如下的参数到如下配置文件

    #/var/lib/kubelet/kubeadm-flags.env
    --resolv-conf=/run/systemd/resolve/resolv.conf
    

让master节点也参与调度

如果需要在master也进行pod调度(k8s默认不进行pod调度) 执行以下指令

# taint命令用于配置污点
#k8s通过设定是否能容忍污点
kubectl taint nodes --all node-role.kubernetes.io/master-

其他节点加入集群

  • 此时需要在要加入集群的服务器上面执行以下指令(当然网段要能访问到,并且已经安装了kubeadm)
kubeadm join xxxxxxxxx:6443 --token xxxxxx.xxxxxxxx --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxx

这时候会出现以下的信息,说明已经成功加入了集群

查看核心组件的状态

kubectl get componentstatus

安装和配置kubernetes-dashboard

安装kubernetes-dashboard

  • 下载官方kubernetes-dashboard的k8s资源文件

    curl -L http://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml -O
    
  • 把资源文件应用到k8s集群

    kubectl create -f kubernetes-dashboard.yaml
    
  • 等待dashboard 完全启动,使用以下命令确认

  • 此时,kubernetes-dashboard已经部署

配置kubernetes-dashboard的rbac策略

kubernetes-dashboard比较坑的地方在于

  • 如果没有配置策略,那么在启动kubernetes-dashboard的时候会出现很多的warning,然后即使能登陆到kubernetes-dashboard,也无法访问里面的资源
  • 配置rbac策略

    #admin-user-admin.rbac.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: admin-user
      namespace: kube-system
    ---
    # Create ClusterRoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: admin-user
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin
    subjects:
    - kind: ServiceAccount
      name: admin-user
      namespace: kube-system
    
  • 应用rbac策略到k8s集群

    kubectl create -f admin-user-admin.rbac.yaml
    

得到用于登陆dashboard的secret

  • 运行命令
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user|awk '{print $1}')
  • 会得到以下的token
Name:         admin-user-token-hmctl
Namespace:    kube-system
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: admin-user
              kubernetes.io/service-account.uid: 00774986-5066-11e9-a0e8-fe242749c541

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  11 bytes
token:      xxxxxxxxxxxxx

使用kubectl proxy在本地打开dashboard

kubectl proxy
  • 访问dashboard

本地浏览器地址栏输入:

localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/

会出现如下的页面:

  • 输入刚刚拿到的令牌

如果没有配置rbac策略,在这个时候,使用令牌即使以admin-user登陆进去,也不能访问里面的资源

  • 然后进入dashboard界面,如下:

此时,已经可以正常访问了

  • 创建能用来访问kubedashboard的config文件

    # 设置集群参数
    export KUBE_APISERVER="https://192.168.56.102:6443"
    kubectl config set-cluster kubernetes \
    --certificate-authority=/etc/kubernetes/pki/ca.crt \
    --embed-certs=true \
    --server=${KUBE_APISERVER} \
    --kubeconfig=devuser.kubeconfig
    
    # 设置客户端认证参数
    #kubectl config set-credentials devuser \
    #--client-certificate=/etc/kubernetes/pki/devuser.pem \
    #--client-key=/etc/kubernetes/pki/devuser-key.pem \
    #--embed-certs=true \
    #--kubeconfig=devuser.kubeconfig
    
    # 设置上下文参数
    kubectl config set-context kubernetes \
    --cluster=kubernetes \
    --user=admin-user \
    --namespace=kube-system \
    --kubeconfig=devuser.kubeconfig
    
    # 设置默认上下文
    kubectl config use-context kubernetes --kubeconfig=devuser.kubeconfig
    
  • 最后在文件后面加上

    users:
    - name: admin-user
      user:
        token: {能正确登陆的token}
    

重新生成join token

kubeadm token create
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
kubeadm join --token {join token} --discovery-token-ca-cert-hash sha256:{证书hash}  {集群ip}:6443 --skip-preflight-checks
kubeadm join --token ccjxkq.6zxymnvz16q13g4h --discovery-token-ca-cert-hash sha256:32810997128e7b7e589f0899a3f9d6b608bb60743e31c61ff3559d7d306cc6d5  108.160.135.88:6443 --skip-preflight-checks