公有云环境: AWS, 腾讯云, 阿里云等等
私有云: OpenStack,vSphere 等
Baremetal 环境: 物理服务器或独立虚拟机 (底层没有云环境).
k8s 部署方式
Minikube:Kubernetes 官网提供的微型分布式环境, 适合学习, 初次体验, 不过应该需要梯子才能用.
Kubeadm: 由于二进制部署方式过于复杂, 所以后来出现了 Kubeadm 的部署方式, 这种方式其实是将 k8s 的各组件容器化了. 注意, 使用容器方式部署 Master 节点各组件时, 需要安装 kubelet 和 docker 组件去实例化容器. 这种方式有些缺点:
这些运行容器所需要的部分镜像在 gcr.io(谷歌的镜像站) 上, 你懂得, 架梯子才能访问.
k8s 集群内部通信采用的是 TLS 认证机制, 但是内部都内网通信, 所以一般采用自建 CA, 此种方式部署, 其中的证书不是自己签的, 所以搞不好啥时候就过期了, 所以生产环境不适用
不支持 Master 节点高可用, 一旦 Master 节点挂了, 容器管理怎么办? 监控, 故障恢复谁处理?
二进制部署: 相对复杂, 生产环境适用. 将重要组件以守护进程的方式部署
还有一些云厂商专有的部署方式, 如 kops, 这里就不一一介绍了.
二次封装的 k8s 发行版
Rancher:Rancher Labs 基于 k8s 的二次封装发行版.
Tectonic:CoreOS 公司基于 k8s 的二次封装发行版.
Openshift:RedHat 基于 k8s 的二次封装发行版, 只留下 k8s 的成熟功能, 部署更加便捷, 需要有 ansible 基础. 相比较知名的发行版就是 Rancher 和 Openshift
k8s 部署要点
测试环境
单 Master, 单 etcd
Node 节点随意.
NFS 存储
生产环境
高可用 Master, 高可用 etcd, 至少三个.
kube-apiserver 是无状态的, 可以配置多实例. 利用 nginx 或者 haproxy 做反代, 并借助 keepalived 实现冗余.
kube-scheduler 和 kube-controller-manager 各自只能有一个活动实例 (同时几个 scheduler 去掉都同一个 Pod, 听谁的.), 但是可以建多个实例备用. 他们自带 leader 选举功能, 且默认开启此功能.
多 Node 主机, 数量越多, 冗余能力越强.
ceph 或 glusterfs 等分布式存储
主机环境预设
如果有条件, 最好搭建一个内网 ntp 服务, 用来同步时间
配置好各节点间的 hosts 解析
禁用防火墙和 Selinux, 防止混淆
各节点禁用 swap, 使用 swap 虽然暂时能节省一些物理内存, 但也会造成性能下降. 安装时会自动检查此项, 不禁用会导致安装出错, 不过也有参数可以忽略...
kubeadm 部署 k8s
主机规划
主机名 | IP | 角色 | 环境 |
---|---|---|---|
k8s-m1 | 192.168.2.124 | 控住节点 | Centos 7.6,配置最少 2 核 CPU,2G 内存 |
k8s-n1 | 192.168.2.244 | 数据节点 | Centos 7.6 |
准备工作 (所有节点)
1. 我没有搭建自己的 ntp, 就用个定时任务替代了吧.
- [[email protected] ~]# crontab -l
- # time sync
- */5 * * * */usr/sbin/ntpdate ntp1.aliyun.com &>/dev/null
2. 配置主机名解析
- [[email protected] ~]# tail -3 /etc/hosts
- 192.168.2.124 k8s-m1
- 192.168.2.244 k8s-n1
3. 关闭防火墙和 selinux
- [[email protected] ~]# systemctl stop firewalld.service
- [[email protected] ~]# systemctl disable firewalld.service
- [[email protected] ~]# sed -i.bak 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config
- [[email protected] ~]# setenforce 0
4. 禁用 swap, 默认情况下系统的 swap 都是打开的.
- # 我在自己电脑上创建的虚拟机做的实验, 资源有限, 这里就不禁用 swap 了. emmmm.... 禁用命令如下:
- [[email protected] ~]# swapoff -a
- # 上面只是临时生效, 永久生效把 fstab 文件中所有的 swap 条目注释掉.
- [[email protected] ~]# cat /etc/fstab | grep swap
- #UUID=0226cdc9-a352-4779-bffb-13e6b794e98b swap swap defaults 0 0
5. 设置开机自动启用 ipvs 内核模块
Node 节点中的 kube-proxy 支持 iptables 和 ipvs 两种模式. 从 v1.2 版本开始, iptables 就作为 kube-proxy 的默认操作模式, v1.8 引入了 ipvs 模式, v1.11 可以正式使用. iptables 和 ipvs 都是基于 netfilter 安全框架, 相比 iptables 来说, ipvs 能够为大型集群提供了更好的扩展性和性能, 并且可以支持更加复杂的负载均衡算法. ipvs 依赖于 iptables, 咱先把准备工作做好, 用不用再说.
- VIM /etc/sysconfig/modules/ipvs.modules
- #!/bin/bash
- ipvs_dir='/usr/lib/modules/`uname -r`/kernel/net/netfilter/ipvs'
- for m in `ls $ipvs_dir | grep -o ^[^.]*`
- do
- /sbin/modinfo -F filename $m &>/dev/null
- if [ $? -eq 0 ];then
- /sbin/modprobe $m
- fi
- done
- # 加载模块的脚本先写好, 放在开机自动加载的 modules 目录中, 但是先不要给执行权限, 咱现在还用不到.
6. 配置免密传输文件. 此步骤可选, 我为了拷贝东西方便.
- [[email protected] ~]# cd /server/scripts/
- [[email protected] scripts]# yum -y install sshpass
- [[email protected] scripts]# VIM batch.sh
- #!/bin/bash
- rm -rf /root/.SSH/id_dsa*
- SSH-keygen -t dsa -f /root/.SSH/id_dsa -P '' -q
- for ip in $*
- do
- sshpass -p 123456 SSH-copy-id -i /root/.SSH/id_dsa.pub -o StrictHostKeyChecking=no 10.0.0.$ip &>/dev/null
- echo -e "\n\033[32m----- 主机 10.0.0.$ip 公钥分发完成 -----\033[0m\n"
- done
- [[email protected] scripts]# sh batch.sh 20 21 22
- [[email protected] scripts]# cd
安装程序 (所有节点)
1. 安装 docker
- [[email protected] ~]# wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- [[email protected] ~]# yum -y install docker-ce
- # docker 自 1.13 版本起, 启动后会默认会把防火墙的 FORWARD 策略改为 DROP, 这可能会影响 k8s 集群的报文转发功能, 所以我们需要将 FORWARD 链的默认策略改为 ACCEPT.
- [[email protected] ~]# VIM /usr/lib/systemd/system/docker.service.
- ExecStartPost=/usr/sbin/iptables -P FORWARD ACCEPT # 当 docker 启动后额外执行此条命令. 此行加到 ExecStart 行下面.
- [[email protected] ~]# systemctl daemon-reload
- [[email protected] ~]# systemctl start docker
- [[email protected] ~]# systemctl enable docker
- # 使用 docker info 命令有报告警信息, 这里如若放任不管, 后面集群初始化和 node 节点加入集群都会报错.
- [[email protected] ~]# docker info
- WARNING: bridge-nf-call-iptables is disabled
- WARNING: bridge-nf-call-ip6tables is disabled
- # 使用下面命令可以看到这俩个参数我们确实没有开启
- [[email protected] ~]# sysctl -a | grep bridge
- net.bridge.bridge-nf-call-ip6tables = 0
- net.bridge.bridge-nf-call-iptables = 0
- [[email protected] ~]# VIM /etc/sysctl.d/k8s.conf
- net.bridge.bridge-nf-call-ip6tables = 1
- net.bridge.bridge-nf-call-iptables = 1
- [[email protected] ~]# sysctl -p /etc/sysctl.d/k8s.conf
- net.bridge.bridge-nf-call-ip6tables = 1
- net.bridge.bridge-nf-call-iptables = 1
2. 配置 k8s 的 yum 仓库, 并安装相关程序. 仓库的配置方法可以在阿里云镜像仓库 https://opsx.alibaba.com/mirror 上的 kubernetes 目录的帮助中查看.
- # 阿里云镜像站的 Kubernetes 项目下 el7 目录中只有一个 repodata, 这种方式表明里面的程序包是按照当前状态构建生成的, 不能够直接下载, 只能本地配置 yum 仓库.
- [[email protected] ~]# VIM /etc/yum.repos.d/kubernetes.repo
- [kubernetes]
- name=kubernetes
- baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
- gpgcheck=1
- gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
- [[email protected] ~]# yum makecache
- [[email protected] ~]# yum -y install kubeadm-1.15.2 kubectl-1.15.2 kubelet-1.15.2
- [[email protected] ~]# systemctl start kubelet.service
- [[email protected] ~]# systemctl enable kubelet.service
修改配置并初始化集群 (master 节点)
1. 修改配置文件, 即便检测到 swap 没有禁用, 也不报错.
- [email protected] ~]# VIM /etc/sysconfig/kubelet
- KUBELET_EXTRA_ARGS="--fail-swap-on=false"
2. kubeadm 命令使用
- [[email protected] ~]# kubeadm --help
- Usage:
- kubeadm [command]
- Available Commands:
- alpha # 处于测试中不太完善的命令
- config # 显示当前配置
- init # 初始化集群
- join # 各 Node 节点加入集群中时使用
- reset # 每个节点都可以用, 把配置还原到最初始的状态.
- upgrade # 升级集群的版本.
- # print 参数也是有子命令的, 使用下面命令可以查看集群初始化时的预设配置, 其中一些与我们真实环境不匹配, 可以在初始化时手动指定修改.
- [[email protected] ~]# kubeadm config print init-defaults # 下面只截取部分配置
- imageRepository: k8s.gcr.io # 默认加载镜像的仓库, 需要梯子才能访问, 如果知道国内别的仓库有需要的镜像, 初始化时可以手动指定仓库地址.
- kind: ClusterConfiguration
- kubernetesVersion: v1.15.2 # k8s 版本, 这是初始化会加载的配置, 如果与你预期的版本不符, 自行修改.
- networking:
- dnsDomain: cluster.local
- serviceSubnet: 10.96.0.0/12 # Service 网络默认地址.
- scheduler: {}
- # 至于 Pod 网络, k8s 只提供了 CNI, 真正实现网络通信, 需要借助第三方插件, 如 flannel,calico, 两者都蛮火的, 不过它们的默认网络地址不同. flannel 的默认地址是 10.244.0.0/16,calico 的默认地址是 192.168.0.0/16. 如果不使用默认地址, 则在部署网路插件时指定的网络地址要与 k8s 部署时指定的 Pod 网络地址一致.
3. 拉取镜像, 并进行 k8s 集群初始化
- # 使用命令行参数. 指定 kubernetes 版本与前面下载 kubeadm 等程序版本一致; 使用 flannel 插件, 所以先指定网络地址; 指定忽略 Swap 的错误检查, 注意大小写; 最后使用 --dry-run 参数测试能否执行成功
- [[email protected] ~]# kubeadm init --kubernetes-version="v1.15.2" --pod-network-cidr="10.244.0.0/16" --ignore-preflight-errors=Swap --dry-run
- [[email protected] ~]# echo $?
- 0
- # 测试是没有问题的, 因为还么有开始拉镜像, 如果去掉 --dry-runde 参数执行, 就会报如下错误: 访问不了 gcr.io.
- [ERROR ImagePull]: failed to pull image k8s.gcr.io/kube-apiserver:v1.15.2: output: Error response from daemon: Get https://k8s.gcr.io/v2/: proxyconnect tcp: dial tcp 218.255.73.143:80: connect: connection refused, error: exit status 1
- # 前面说过, kubeadm 部署的 k8s 需要用到的镜像有一部分在 k8s.gcr.io 上, 因为某种不可描述的原因导致我们拉取不到, 所以只能找找国内的资源, 可以先看看 kubeadm 需要哪些镜像.
- [[email protected] ~]# kubeadm config images list
- W0812 14:25:08.711840 4589 version.go:98] could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable-1.txt": Get https://dl.k8s.io/release/stable-1.txt: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers) # 访问不到 grc.io
- W0812 14:25:08.711926 4589 version.go:99] falling back to the local client version: v1.15.2 # 本地客户端版本
- k8s.gcr.io/kube-apiserver:v1.15.2
- k8s.gcr.io/kube-controller-manager:v1.15.2
- k8s.gcr.io/kube-scheduler:v1.15.2
- k8s.gcr.io/kube-proxy:v1.15.2
- k8s.gcr.io/pause:3.1
- k8s.gcr.io/etcd:3.3.10
- k8s.gcr.io/coredns:1.3.1
- # 手动下载镜像, 然后修改 tag
- [[email protected] ~]# docker pull mirrorgooglecontainers/kube-apiserver:v1.15.2
- [[email protected] ~]# docker pull mirrorgooglecontainers/kube-controller-manager-amd64:v1.15.2
- [[email protected] ~]# docker pull mirrorgooglecontainers/kube-scheduler-amd64:v1.15.2
- [[email protected] ~]# docker pull mirrorgooglecontainers/kube-proxy:v1.15.2
- [[email protected] ~]# docker pull mirrorgooglecontainers/pause:3.1
- [[email protected] ~]# docker pull mirrorgooglecontainers/etcd:3.3.10
- [[email protected] ~]# docker pull coredns/coredns:1.3.1
- [[email protected] ~]# docker tag mirrorgooglecontainers/kube-apiserver:v1.15.2 k8s.gcr.io/kube-apiserver:v1.15.2
- [[email protected] ~]# docker tag mirrorgooglecontainers/kube-controller-manager-amd64:v1.15.2 k8s.gcr.io/kube-controller-manager:v1.15.2
- [[email protected] ~]# docker tag mirrorgooglecontainers/kube-scheduler-amd64:v1.15.2 k8s.gcr.io/kube-scheduler:v1.15.2
- [[email protected] ~]# docker tag mirrorgooglecontainers/kube-proxy:v1.15.2 k8s.gcr.io/kube-proxy:v1.15.2
- [[email protected] ~]# docker tag mirrorgooglecontainers/pause:3.1 k8s.gcr.io/pause:3.1
- [[email protected] ~]# docker tag mirrorgooglecontainers/etcd:3.3.10 k8s.gcr.io/etcd:3.3.10
- [[email protected] ~]# docker tag coredns/coredns:1.3.1 k8s.gcr.io/coredns:1.3.1
- # 删除掉不用的镜像, 最终如下:
- [[email protected] ~]# docker images
- REPOSITORY TAG IMAGE ID CREATED SIZE
- k8s.gcr.io/kube-apiserver v1.15.2 34a53be6c9a7 6 days ago 207MB
- k8s.gcr.io/kube-proxy v1.15.2 167bbf6c9338 6 days ago 82.4MB
- k8s.gcr.io/kube-scheduler v1.15.2 38d61dd6e105 3 weeks ago 81.1MB
- k8s.gcr.io/kube-controller-manager v1.15.2 575346c7506b 3 weeks ago 159MB
- k8s.gcr.io/coredns 1.3.1 eb516548c180 7 months ago 40.3MB
- k8s.gcr.io/etcd 3.3.10 2c4adeb21b4f 8 months ago 258MB
- k8s.gcr.io/pause 3.1 da86e6ba6ca1 19 months ago 742kB
- # 开始执行初始化操作. 如果初始化出错, 可以使用 kubeadm reset 命令删除初始化过程产生的文件, 重置到初始状态.
- [[email protected] ~]# kubeadm init --kubernetes-version="v1.15.2" --pod-network-cidr="10.244.0.0/16" --service-cidr="10.96.0.0/12" --apiserver-advertise-address="0.0.0.0" --ignore-preflight-errors=Swap
- Your Kubernetes control-plane has initialized successfully!
- To start using your cluster, you need to run the following as a regular user: # 以普通用户执行下面命令
- mkdir -p $HOME/.kube
- sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
- sudo chown $(id -u):$(id -g) $HOME/.kube/config
- You should now deploy a pod network to the cluster. # 提示需要安装网络插件
- Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
- https://kubernetes.io/docs/concepts/cluster-administration/addons/
- Then you can join any number of worker nodes by running the following on each as root:
- kubeadm join 192.168.2.124:6443 --token a6o1sb.30kajnbrq83qnr8r --discovery-token-ca-cert-hash sha256:f46d7a79ec6e939c44a4c0425c892fa9ee816012ef2f675ac36002b2473210e3 # Node 节点加入集群的命令, 注意保存.
- # 此处为了方便就直接用 root 用户进行操作了.
- [[email protected] ~]# mkdir -p $HOME/.kube
- [[email protected] ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
- [[email protected] ~]# chown $(id -u):$(id -g) $HOME/.kube/config # 管理员下此步骤可省略
- # 查看集群当前的状态
- [[email protected] ~]# kubectl get cs
- NAME STATUS MESSAGE ERROR
- controller-manager Healthy ok
- scheduler Healthy ok
- etcd-0 Healthy {"health":"true"}
- # 查看集群版本
- [[email protected] ~]# kubectl version --short=true
- Client Version: v1.15.2
- Server Version: v1.15.2
- # 查看集群信息
- [[email protected] ~]# kubectl cluster-info
- Kubernetes master is running at https://192.168.2.124:6443
- KubeDNS is running at https://192.168.2.124:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
- To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
- # config 的配置文件是一定要有的, 没有的话, kubectl get nodes 命令就执行不了, 注意配置文件一定不能泄露. node 上也有此命令, 但是不能执行 get 的操作, 因为 apiserver 监听在 master 的 6443 的端口, 除非你 master 节点的配置文件拷贝到 node 上, 否则 node 执行 kubectl get nodes 就只会找本机的 8080, 这是没有结果的.
- [[email protected] ~]# netstat -lntp | grep -i apiserve
- tcp6 0 0 :::6443 :::* LISTEN 16341/kube-apiserve
- [[email protected] ~]# kubectl config view | grep server
- server: https://192.168.2.124:6443
- [[email protected] ~]# kubectl get nodes
- The connection to the server localhost:8080 was refused - did you specify the right host or port?
- # 现在只有一个 master 节点, 状态是未就绪, 需要部署网络插件.
- [[email protected] ~]# kubectl get nodes
- NAME STATUS ROLES AGE VERSION
- k8s-m1 NotReady master 18m v1.15.2
4. 部署 flannel 网络插件, 部署的命令在 GitHub https://github.com/coreos/flannel 页面搜索 "Deploying flannel manually" 就可以找到.
- [[email protected] ~]# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
- # 安装完看下 Pod 的运行状态
- [[email protected] ~]# kubectl get pods
- No resources found.
- # 没有找到是因为集群本身是被划分为多个名称空间的, kubectl get pods 命令默认查的是 default 名称空间
- [[email protected] ~]# kubectl get ns
- NAME STATUS AGE
- default Active 14m
- kube-node-lease Active 15m
- kube-public Active 15m
- kube-system Active 15m
- # 使用 - n 的参数指定查找名称空间下的 Pod.flannel 插件到 running 的状态取决于网速
- [[email protected] ~]# kubectl get pods -n kube-system
- NAME READY STATUS RESTARTS AGE
- coredns-5c98db65d4-mzw28 1/1 Running 0 14m
- coredns-5c98db65d4-zl5cs 1/1 Running 0 14m
- etcd-k8s-m1 1/1 Running 0 13m
- kube-apiserver-k8s-m1 1/1 Running 0 13m
- kube-controller-manager-k8s-m1 1/1 Running 0 13m
- kube-flannel-ds-amd64-qd5js 1/1 Running 0 112s
- kube-proxy-9p5qd 1/1 Running 0 14m
- kube-scheduler-k8s-m1 1/1 Running 0 13m
- [[email protected] ~]# kubectl get nodes
- NAME STATUS ROLES AGE VERSION
- k8s-m1 Ready master 15m v1.15.2
- # 这些组件都是以 Pod 的方式启动, 可以查看本机启动的容器, 名字都是以 Pod 开头的.
- [[email protected] ~]# docker ps -a
配置 Node 节点加入到 k8s 集群 (所有 Node 节点)
1. 修改配置文件.
- [email protected] ~]# VIM /etc/sysconfig/kubelet
- KUBELET_EXTRA_ARGS="--fail-swap-on=false"
2. node 节点加入集群时, 也是需要容器方式启动一些组件的, 这里你就直接从 k8s-m1 导出再导入到 node 节点.
来源: http://www.bubuko.com/infodetail-3340396.html