kubeadm部署k8s集群

kubeadm部署k8s集群

k8s集群的安装

1.搭建k8s环境平台规划

平台规划

单master集群

image-20201218153918232

多master集群

image-20201218154126651

2.服务器硬件配置要求

测试环境

image-20201218154340528

生产环境

更高要求 16核

3.搭建k8s集群部署方式

①kubeadm

kubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群

官方地址https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/

②二进制包

从github下载发行版的二进制包,手动部署每个组件,组成Kubernetes集群。推荐使用二进制包的方式搭建k8s。

k8s构建
master: etcd api-server controller-manager   scheduler
node:    kubelet   kube-proxy
kubelet作用: 接收api-server的指令,调用docker启动容器
kube-proxy作用:负载均衡   service
etcd作用: 数据库     yaml      kubectl  create  delete get describe  edit 
是Kubernetes提供默认的存储系统,保存所有集群数据,使用时需要为etcd数据提供备份计划
scheduler的作用: 调度策略     
controller-manager的作用:rc  deployment

kubeadm部署k8s集群架构

核心组件:

image-20201211191017709

image-20201209091056224

image-20201218170921711

​ Add-ons:

组件名称 说明
kube-dns 负责为整个集群提供DNS服务
Ingress Controller 为服务提供外网入口
Heapster 提供资源监控
Dashboard 提供GUI
Federation 提供跨可用区的集群
Fluentd-elasticsearch 提供集群日志采集、存储与查询

环境准备

一台或多台机器操作系统 CentOS7.x-86 x64

硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30G或更多

集群中所有机器之间网络互通

可以访问外网,需要拉取镜像

禁止swap分区

10.0.0.11 k8s-master
10.0.0.12 k8s-node-1
10.0.0.13 k8s-node-2
systemctl stop firewalld
systemctl disable firewalld

sed -i 's/SELINUX=enforcing/SELINUX=disabled/g'/etc/selinux/config

swapoff -a  
sed -ri 's/.*swap.*/#&/' /etc/fstab  #防止开机自动挂载swap
hostnamectl set-hostname 主机名
sed -i 's/200/IP/g' /etc/sysconfig/network-scripts/ifcfg-eth0
节省iptables4的流量
cat > /etc/sysctl.d/k8s.conf<<EOF
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-iptables=1
EOF
sysctl --system #生效


yum -y install ntpdate      时间同步
ntpdate time.windows.com
master节点
cat > /etc/hosts <<EOF
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.11 k8s-master
10.0.0.12 k8s-node-1
10.0.0.13 k8s-node-2
EOF
scp -rp /etc/hosts root@10.0.0.12:/etc/hosts
scp -rp /etc/hosts root@10.0.0.13:/etc/hosts

master部署

etcd

https://github.com/etcd-io/etcd/releases

  1. 安装
yum install etcd -y
  1. 配置
sed -i "6c ETCD_LISTEN_CLIENT_URLS=\"http://0.0.0.0:2379\"" /etc/etcd/etcd.conf
sed -i "21c ETCD_ADVERTISE_CLIENT_URLS=\"http://10.0.0.11:2379\"" /etc/etcd/etcd.conf
sed -i "6c ETCD_LISTEN_CLIENT_URLS=\"http://0.0.0.0:2379\"" /etc/etcd/etcd.conf
sed -i "21c ETCD_ADVERTISE_CLIENT_URLS=\"http://10.0.0.11:2379\"" /etc/etcd/etcd.conf
a [\]text 在指定行后面追加文本,支持使用\n实现多行追加
i [\]text 在行前面插入文本
c [\]text 替换行为单行或多行文本
#[Member]
#ETCD_CORS=""
ETCD_DATA_DIR="/var/lib/etcd/default.etcd" # 数据文件存放路径
#ETCD_WAL_DIR=""
#ETCD_LISTEN_PEER_URLS="http://localhost:2380" # 同类监听地址,用于集群时同步
ETCD_LISTEN_CLIENT_URLS="http://localhost:2379" # 客户端监听地址
#ETCD_MAX_SNAPSHOTS="5"  # 快照最大数量
#ETCD_MAX_WALS="5"
ETCD_NAME="default"      # 服务名,集群时不能一样
... ...
#
#[Clustering]
#ETCD_INITIAL_ADVERTISE_PEER_URLS="http://localhost:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"
... ...
  1. 启动并加入开机启动
systemctl start etcd.service
systemctl enable etcd.service
  1. 检查集群健康状态
etcdctl -C http://10.0.0.11:2379 cluster-health
  1. etcdctl命令介绍
etcdctl [global options] command [command options] [arguments...]

etcdctl mk [command options] <key> <value>
etcdctl ls [command options] [key]
etcdctl set [command options] <key> <value>
etcdctl get [command options] <key>

backup          # 备份etcd目录
cluster-health  # 检查etcd群集的运行状况
mk              # 生成一个具有给定值的新键
mkdir           # 创建新目录
rm              # 删除键或目录
rmdir           # 删除键。如果是空目录或键值对
get             # 检索键的值
ls              # 检索目录
set             # 设置键的值
setdir          # 创建新目录或更新现有目录TTL
update          # 使用给定值更新现有密钥
updatedir       # 更新现有目录
watch           # 观察键的变化
exec-watch      # 观察一个键的变化并执行一个可执行文件
member          # 成员add、remove和list子命令
user            # 用户add、grant和revoke子命令
role            # 角色add、grant和revoke子命令
auth            # 总体身份验证控制

kubernetes-master

  1. 安装
yum install kubernetes-master -y
  1. 配置apiserver
sed -i "8c KUBE_API_ADDRESS=\"--insecure-bind-address=0.0.0.0\"" /etc/kubernetes/apiserver
sed -i "11c KUBE_API_PORT=\"--port=8080\"" /etc/kubernetes/apiserver
sed -i "14c KUBELET_PORT=\"--kubelet-port=10250\"" /etc/kubernetes/apiserver
sed -i "17c KUBE_ETCD_SERVERS=\"--etcd-servers=http://10.0.0.11:2379\"" /etc/kubernetes/apiserver
sed -i "s/ServiceAccount,//" /etc/kubernetes/apiserver

默认配置文件:

###
# kubernetes system config
#
# The following values are used to configure the kube-apiserver
#

# The address on the local server to listen to.
KUBE_API_ADDRESS="--insecure-bind-address=127.0.0.1"

# The port on the local server to listen on.
# KUBE_API_PORT="--port=8080"

# Port minions listen on
# KUBELET_PORT="--kubelet-port=10250"

# Comma separated list of nodes in the etcd cluster
KUBE_ETCD_SERVERS="--etcd-servers=http://127.0.0.1:2379"

# Address range to use for services
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"

# default admission control policies
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"

# Add your own!
KUBE_API_ARGS=""
  1. 配置config
sed -i "22c KUBE_MASTER=\"--master=http://10.0.0.11:8080\"" /etc/kubernetes/config

默认配置文件:

###
# kubernetes system config
#
# The following values are used to configure various aspects of all
# kubernetes services, including
#
#   kube-apiserver.service
#   kube-controller-manager.service
#   kube-scheduler.service
#   kubelet.service
#   kube-proxy.service
# logging to stderr means we get it in the systemd journal
KUBE_LOGTOSTDERR="--logtostderr=true"

# journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"

# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=false"

# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=http://127.0.0.1:8080"
  1. 启动并加入开机启动
systemctl enable kube-apiserver.service
systemctl enable kube-controller-manager.service
systemctl enable kube-scheduler.service
systemctl start kube-apiserver.service
systemctl start kube-controller-manager.service
systemctl start kube-scheduler.service
  1. 检查服务是否安装正常
[root@k8s-master ~]# kubectl get componentstatus
NAME                 STATUS    MESSAGE             ERROR
etcd-0               Healthy   {"health":"true"}   
scheduler            Healthy   ok                  
controller-manager   Healthy   ok

node部署

kubernetes-node(集成cadvisor)

  1. 安装
yum install kubernetes-node -y
  1. 配置config
sed -i "22c KUBE_MASTER=\"--master=http://10.0.0.11:8080\"" /etc/kubernetes/config
  1. 配置kubelet
sed -i "5c KUBELET_ADDRESS=\"--address=0.0.0.0\"" /etc/kubernetes/kubelet
sed -i "8c KUBELET_PORT=\"--port=10250\"" /etc/kubernetes/kubelet
sed -i "14c KUBELET_API_SERVER=\"--api-servers=http://10.0.0.11:8080\"" /etc/kubernetes/kubelet

k8s-node-1:10.0.0.12

sed -i "11c KUBELET_HOSTNAME=\"--hostname-override=10.0.0.12\"" /etc/kubernetes/kubelet

k8s-node-2:10.0.0.13

sed -i "11c KUBELET_HOSTNAME=\"--hostname-override=10.0.0.13\"" /etc/kubernetes/kubelet

默认配置文件:

###
# kubernetes kubelet (minion) config

# The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)
KUBELET_ADDRESS="--address=127.0.0.1"

# The port for the info server to serve on
# KUBELET_PORT="--port=10250"

# You may leave this blank to use the actual hostname
KUBELET_HOSTNAME="--hostname-override=127.0.0.1"

# location of the api-server
KUBELET_API_SERVER="--api-servers=http://127.0.0.1:8080"

# pod infrastructure container
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrast
ructure:latest"

# Add your own!
KUBELET_ARGS=""
  1. 启动并加入开机启动
systemctl enable docker
systemctl enable kubelet.service
systemctl enable kube-proxy.service
systemctl start kubelet.service
systemctl start kube-proxy.service
  1. 在master节点检查
kubectl get nodes
  1. 访问cadvisor的web界面:

所有节点配置flannel网络

  1. 安装
yum install flannel -y
  1. 配置
sed -i 's#127.0.0.1#10.0.0.11#g' /etc/sysconfig/flanneld
  1. master节点创建key,安装docker启动并加入开机启动
etcdctl mk /atomic.io/network/config '{ "Network": "172.18.0.0/16","Backend": {"Type": "vxlan"} }'

flannel三种模式:

  • udp:性能最差
  • vxlan:性能较好
  • host-gw:性能最好,但云主机不能用
yum install docker -y
systemctl enable docker
systemctl start docker
  1. 启动并加入开机启动
systemctl enable flanneld.service
systemctl start flanneld.service

docker指定bip设置docker0网卡的IP

  1. 配置docker服务启动文件:启动时设置iptables规则允许转发
sed -i "/ExecStart=/i ExecStartPost=/usr/sbin/iptables -P FORWARD ACCEPT" /usr/lib/systemd/system/docker.service
systemctl daemon-reload
systemctl restart docker
  1. 查看flannel网卡
ifconfig flannel0
  1. 验证各节点互通
docker run -it alpine
ifconfig
  1. 配置仓库信任和加速
cat > /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": ["https://registry.docker-cn.com"],
  "insecure-registries": ["10.0.0.11:5000"]
}
EOF
systemctl restart docker

master部署镜像仓库

docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry registry

node提交镜像测试

docker tag alpine:3.9 10.0.0.11:5000/alpine:3.9
docker push 10.0.0.11:5000/alpine:3.9

查看仓库镜像文件

ls /opt/myregistry/docker/registry/v2/repositories

kubernetes集群命令行工具kubectl

kubectl语法格式

kubectl [command] [TYPE] [NAME] [flags]

command:指定要对资源执行的操作,例如create,get,describe和delete

TYPE:指定资源类型,资源类型是大小写敏感的,开发者能够以单数,复数和缩略的形式

例如:

kubectl get pod pod1

kubectl get pods pod1

NAME:指定资源的名称,名称大小写敏感,如果省略名称,则会显示所有的资源,

kubectl get pods

flags:指定可选的参数,例如,可用-s或者-server参数指定Kubernetes API server的地址和端口

kubectl --help获取更多信息

kubectl get --help 具体查看某个操作

#基础命令
create  通过文件名或标准输入创建资源
expose 讲一个资源公开为一个新的Service
run 在集群中运行一个特定的镜像
set 在对象上设置特定的功能
get 显示一个或多个资源
explain 文档参考资料
edit 使用默认的编辑器编辑一个资源
delete  通过文件名,标准输入,资源名称或标签选择器来删除资源

部署和集群管理命令
rollout  管理资源的发布
rolling-update  对给定的复制控制器滚动更新
scale 扩容或缩容Pod数量,Deployment,ReplicaSet,RC或Job
autoscale 创建一个自动选择扩容或缩容并设置Pod数量
certificate 修改证书资源
cluster-info 显示集群信息
top 显示资源(CPU/Memory/Storage)使用,需要Heapster运行;
cordon  标记节点不可调度
uncordon 标记节点可调度
drain 驱逐节点上的应用,准备下线维护
taint 修改节点taint标记

故障和调试命令
describe   显示特定资源或资源组的详细信息
logs   在一个Pod中打印一个容器日志,如果Pod只有一个容器,容器名称是可选的
attach  附加到一个运行的容器
exec   执行命令到容器
port-forward  转发一个或多个本地端口到一个pod
proxy 运行一个proxy到Kubernetes API Server
cp 拷贝文件或目录到容器中
auth  检查授权


#其他命令
高级命令   
apply  通过文件名或标准输入对资源应用配置
patch  使用补丁修改,更新资源的字段
replace 通过文件名或标准输入替换一个资源
convert 不同的API版本之间转换配置文件

设置命令
label   更新资源上的标签
annotate  更新资源上的注释
completion 用于实现kubectl工具自动补全

其他命令
api-versions 打印受支持的API版本
config  修改kubeconfig文件(用于访问API,比如配置认证信息)
help   所有命令帮助
plugin 运行一个命令行插件
version 打印客户端和服务版本信息

kubeadm命令详解

--apiserver-advertise-address string    #API Server 将要监听的监听地址
--apiserver-bind-port int32 # API Server绑定的端口默认为6443,
--apiserver-cert-extra-sans stringSlice # 可选的证书额外信息,用于指定API Server的服务器证书。可以是IP地址也可以是DNS名称。
--cert-dir string    # 证书的存储路径,缺省路径为/etc/kubernetes/pki
--config string    #kubeadm配置文件的路径
--ignore-preflight-errors strings #可以忽略检查过程中出现的错误信息,比如忽略swap,如果为all就忽略所有
--image-repository string # 设置一个镜像仓库,默认为k8s.gcr.io
--kubernetes-version string # 选择k8s版本,默认为stable1
--node-name string # 指定node名称
--pod-network-cidr # 设置pod ip地址范围
--service-cidr # 设置service网络地址范围
--service-dns-domain string # 设置域名,默认为cluster.local
--skip-certificate-key-print # 不打印用于加密的key信息
--skip-phases strings # 要跳过哪些阶段
--skip-token-print # 跳过打印token信息
--token # 指定token
--token-ttl #指定token过期时间,默认为24小时,0为永不过期
--upload-certs #更新证书
 
全局选项
--log-file string        #日志路径
--log-file-max-size uint #设置日志文件的最大大小,单位为兆,默认为18000为没有限制rootfs #宿主机的根路径,也就是使用绝对路径
--skip-headers #为true,在log日志里面不显示消息的头部信息
--skip-log-headers #为true在日志文件里面不记录头部信息

YAML文件

资源清单文件

资源编排

1.语法格式

通过缩进表示层级关系

不能使用Tab进行缩进,只能使用空格

一般开头缩进两个空格

字符号后缩进一个空格,比如冒号,逗号等后面

使用---表示新的yaml文件开始

使用#代表注释

2.yaml文件组成部分

控制器定义

被控制对象

3.常用字段含义

image-20201218182642883

4.快速编写yaml文件

第一种使用kubectl create命令生成yaml文件

kubectl   create  deployment  web  --image=nginx -o yaml  --dry-run > my1.yaml

第二种使用kubectl get命令导出yaml文件

kubectl get  deploy
kubectl  get  deploy  nginx  -o=yaml  --export  >my2.yaml

k8s简介

https://kubernetes.io

k8s是一个docker集群的管理工具 ,是容器的编排工具

k8s的历史

  • 2013年:docker开源,容器

  • 2014年 docker容器编排工9999具,立项 谷歌15年运维生产经验borg borg-monitor

  • 2015年7月 发布kubernetes 1.0, 加入cncf基金会 孵化

  • 2016年,kubernetes干掉两个对手,docker swarm,mesos marathon 1.2版

  • 2017年 1.5 -1.9

  • 2018年 k8s 从cncf基金会 毕业项目1.10 1.11 1.12

  • 2019年: 1.13, 1.14 ,1.15,1.16 1.17

cncf :cloud native compute foundation 孵化器

kubernetes (k8s): 希腊语 舵手,领航者 容器编排领域,

谷歌15年容器使用经验,borg容器管理平台,使用golang重构borg,kubernetes

cncf 基金会 谷歌公司牵头成立

k8s核心功能:

自我修复: 重新启动失败的容器,在节点不可用时,替换和重新调度节点上的容器,对用户定义的健康检查不响应的容器会被中止,并且在容器准备好服务之前不会把其向客户端广播。

弹性伸缩: 通过监控容器的cpu的负载值,如果这个平均高于80%,增加容器的数量;如果这个平均低于10%,减少容器的数量。

服务的自动发现和负载均衡:不需要修改您的应用程序来使用不熟悉的服务发现机制,Kubernetes 为容器提供了自己的 IP 地址和一组容器的单个 DNS 名称,并可以在它们之间进行负载均衡。

滚动升级和一键回滚:

Kubernetes 逐渐部署对应用程序或其配置的更改,同时监视应用程序运行状况,以确保它不会同时终止所有实例。 如果出现问题,Kubernetes会为您恢复更改,利用日益增长的部署解决方案的生态系统。

容器服务升级

1:打包新版本镜像

2:停掉老容器

3:启动新容器

私密配置文件管理 web容器里面,数据库的账户密码(测试库密码)

k8s的安装方式

yum安装 1.5 最容易安装成功,最适合学习的

源码编译安装---难度最大 可以安装最新版

二进制安装---步骤繁琐 可以安装最新版 shell,ansible,saltstack,适合生产

kubeadm 安装最容易, 网络 可以安装最新版 适合生产

minikube 适合开发人员体验k8s, 国外网络

k8s最适合跑微服务项目!

微服务:mvc架构

mvc业务:只有一套架构集群

软件开发架构:model viewer controller

微服务架构:拆业务

N+套架构

微服务架构:支持更多的并发,网站高可用性更强,业务更加健壮,代码更新更快

京东 订单 快递员的轨迹

微服务架构-------拆成100个业务

java tomcat | java tomcat

消息队列 RabbitMQ kafka redis

虚拟机:物理机

300套:tomcat

docker tomcat + code

k8s开机检查

kubectl get componentstatus
kubectl get nodes
kubectl get pod -o wide
[root@k8s-master ~]# kubectl get componentstatus # 检查组件状态
NAME                 STATUS    MESSAGE             ERROR
etcd-0               Healthy   {"health":"true"}   
scheduler            Healthy   ok                  
controller-manager   Healthy   ok                  
[root@k8s-master ~]# kubectl get nodes # 检查nodes节点状态
NAME        STATUS    AGE
10.0.0.12   Ready     21m
10.0.0.13   Ready     3d
[root@k8s-master ~]# kubectl get pod -o wide # 检查pod节点状态
NAME          READY     STATUS    RESTARTS   AGE       IP             NODE
nginx-8phch   1/1       Running   1          13h       172.18.100.2   10.0.0.13
nginx-dc8wc   1/1       Running   1          13h       172.18.100.3   10.0.0.13
nginx-kcmpv   1/1       Running   1          13h       172.18.100.4   10.0.0.13
nginx-mknrb   1/1       Running   1          13h       172.18.100.6   10.0.0.13
nginx-zk9kg   1/1       Running   0          8s        172.18.68.2    10.0.0.12
[root@k8s-master ~]# ping 172.18.100.2
PING 172.18.100.2 (172.18.100.2) 56(84) bytes of data.
64 bytes from 172.18.100.2: icmp_seq=1 ttl=63 time=3.82 ms
64 bytes from 172.18.100.2: icmp_seq=2 ttl=63 time=0.380 ms
^C
--- 172.18.100.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.380/2.104/3.829/1.725 ms
[root@k8s-master ~]# ping 172.18.68.2
PING 172.18.68.2 (172.18.68.2) 56(84) bytes of data.
64 bytes from 172.18.68.2: icmp_seq=1 ttl=63 time=2.48 ms
64 bytes from 172.18.68.2: icmp_seq=2 ttl=63 time=0.354 ms
^C
--- 172.18.68.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.354/1.421/2.488/1.067 ms

k8s资源

创建pod资源

准备:

node下载镜像,上传至私有仓库

docker pull nginx:1.13
docker tag docker.io/nginx:1.13 10.0.0.11:5000/nginx:1.13
docker push 10.0.0.11:5000/nginx:1.13
docker pull nginx:1.15
docker tag docker.io/nginx:1.15 10.0.0.11:5000/nginx:1.15
docker push 10.0.0.11:5000/nginx:1.15
docker pull alpine
docker tag docker.io/alpine:latest 10.0.0.11:5000/alpine:latest
docker push 10.0.0.11:5000/alpine:latest

注:解决软连接失效的问题

安装pod-infrastructure

重启 systemctl restart kube-scheduler.service

pod资源和容器的关系

Pod(容器组)是 Kubernetes 中最小的调度单元,可以通过 yaml 定义文件直接创建一个 Pod。但 Pod 本身并不具备自我恢复(self-healing)功能。如果一个 Pod 所在的节点出现故障,或者调度程序自身出现问题,以及节点资源不够或节点进入维护而驱逐 Pod 时,Pod 将被删除,且不能自我恢复。

pod

最小部署单元

包含多个容器(一组容器的集合)

一个pod中容器共享网络命名空间

pod的生命周期是短暂的

创建一个pod资源,启动了2个容器

一个基础容器pod

一个业务容器nginx

pod存在意义

①创建容器使用docker,一个docker对应一个容器,一个容器有进程,一个容器运行一个应用程序

②pod是多进程程序设计,运行多个应用程序

一个Pod有多个容器,一个容器里面运行一个应用程序

③Pod存在为了亲密性应用

两个应用之间进行交互

网络之间调用

两个应用需要频繁调用

3.Pod实现机制

①共享网络

容器本身之间相互隔离的

namespace

group

前提条件

容器在同一个ns里面

pod实现共享网络机制

​ pod容器----->info容器

首先创建Pause容器,然后创建业务容器

共享网络:通过Pause容器,把其他业务容器加入到Pause容器里面,让所有业务容器在同一个名称空间中,可以实现网络共享

image-20201218194641876

②共享存储

Pod实现机制 共享存储

pod持久化数据 日志数据 业务数据

image-20201218195816263

共享存储:引入数据卷概念Volumn,使用数据卷进行持久化存储

4Pod镜像拉取策略

IfNotPresent:默认值,镜像在宿主机上不存在时才拉取

Always:每次创建Pod都会重新拉取一次镜像

Never: Pod永远不会主动拉取这个镜像

5.Pod资源限制

image-20201218202735621

6.Pod重启策略

Always: 当容器终止退出后,总是重启容器,默认策略

OnFailure: 当容器异常退出(退出状态码非0)时,才重启容器。

Never: 当容器终止退出,从不重启容器。

7.Pod健康检查

容器检查

java堆内存溢出

应用层面健康检查

livenessProbe(存活检查)

如果检查失败,将杀死容器,根据Pod的restartPolicy来操作

readinessProbe(就绪检查)

如果检查失败,Kubernetes会把Pod从service endpoints中剔除

Probe支持一下三种检查方法:

httpget

发送HTTP请求,返回200-400范围状态码为成功

exec

执行Shell命令返回状态码是0为成功;

tcpsocker

发送 TCP SOCKET 建立成功。.

8.Pod调度策略

创建pod流程

master节点

createpod -- apiserver --etcd

scheduler --apiserver --etcd -- 调度算法,把pod调度某个node节点上

node节点

kublet --apiserver --读取etcd拿到分配给当前节点pod -- docker创建容器

9.Pod调度影响因素

(1)Pod资源限制对Pod调用产生影响

根据request找到足够node节点进行调度

image-20201218211808344

(2)节点选择器标签影响Pod标签

image-20201218211825284

(3)节点亲和性影响Pod调度

节点亲和性 nodeAffinity和之前nodeSelector基本一样的,根据节点上标签约束来绝对Pod调度到哪些节点上

a.硬亲和性

约束条件必须满足

image-20201218212828507

b.软亲和性

尝试满足,不保证

支持常用操作符

In NotIn Exists Gt DoesNotExists

image-20201218213125168

反亲和性

影响pod调度

4.污点和污点容忍

基本介绍

nodeSelector和nodeAffinity: Pod调度到某些节点上,Pod属性,调度时候实现

Taint污点: 节点不做普通分配调度,是节点属性

2.场景

专用场景

配置特点硬件节点

基于Taint驱逐

3.具体演示

(1)查看节点污点情况

image-20201218214046725

污点值有三个

NoSchedule: 一定不被调度

PreferNoSchedule:尽量不被调度

NoExecute: 不会调度,并且还会驱逐Node已有Pod

(2)为节点添加污点

kubectl taint node [node] key=value:污点三个值

(3)删除污点

image-20201218214743720

4.污点容忍

image-20201218214958338

任何一个k8s资源都可以由yml清单文件来定义。

apiVersion: v1       # 版本号
kind: Pod            # Pod
metadata:            # 元数据
  name: string       # Pod名称
  namespace: string  # Pod所属的命名空间
  labels:            # 自定义标签
    - name: string   # 自定义标签名字
  annotations:       # 自定义注释列表
    - name: string
spec:                # Pod中容器的详细定义
  containers:        # Pod中容器列表
  - name: string     # 容器名称
    image: string    # 容器的镜像名称
    imagePullPolicy: [Always | Never | IfNotPresent] # 获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像
    command: [string]  # 容器的启动命令列表,如不指定,使用打包时使用的启动命令
    args: [string]     # 容器的启动命令参数列表
    workingDir: string # 容器的工作目录
    volumeMounts:      # 挂载到容器内部的存储卷配置
    - name: string     # 引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名
      mountPath: string    # 存储卷在容器内mount的绝对路径,应少于512字符
      readOnly: boolean    # 是否为只读模式
    ports:             # 需要暴露的端口库号列表
    - name: string     # 端口号名称
      containerPort: int   # 容器需要监听的端口号
      hostPort: int    # 容器所在主机需要监听的端口号,默认与Container相同
      protocol: string # 端口协议,支持TCP和UDP,默认TCP
    env:               # 容器运行前需设置的环境变量列表
    - name: string     # 环境变量名称
      value: string    # 环境变量的值
    resources:         # 资源限制和请求的设置
      limits:          # 资源限制的设置
        cpu: string    #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数
        memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数
      requests:        # 资源请求的设置
        cpu: string    # Cpu请求,容器启动的初始可用数量
        memory: string # 内存请求,容器启动的初始可用数量
    livenessProbe:     # 对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可
      exec:          # 对Pod容器内检查方式设置为exec方式
        command: [string]  # exec方式需要制定的命令或脚本
      httpGet:       # 对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket:     # 对Pod内个容器健康检查方式设置为tcpSocket方式
         port: number
       initialDelaySeconds: 0  # 容器启动完成后首次探测的时间,单位为秒
       timeoutSeconds: 0   # 对容器健康检查探测等待响应的超时时间,单位秒,默认1秒
       periodSeconds: 0    # 对容器监控检查的定期探测时间设置,单位秒,默认10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged:false
    restartPolicy: [Always | Never | OnFailure] # Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该Pod
    nodeSelector: obeject  # 设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定
    imagePullSecrets:      # Pull镜像时使用的secret名称,以key:secretkey格式指定
    - name: string
    hostNetwork:false      # 是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络
    volumes:           # 在该pod上定义共享存储卷列表
    - name: string     # 共享存储卷名称 (volumes类型有很多种)
      emptyDir: {}     # 类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值
      hostPath: string # 类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录
        path: string   # Pod所在宿主机的目录,将被用于同期中mount的目录
      secret:          # 类型为secret的存储卷,挂载集群与定义的secre对象到容器内部
        scretname: string  
        items:     
        - key: string
          path: string
      configMap:      # 类型为configMap的存储卷,挂载预定义的configMap对象到容器内部
        name: string
        items:
        - key: string
          path: string

k8s yaml的主要组成:

  • apiVersion:v1 :api版本
  • kind:pod :资源类型
  • metadata :属性
  • spec :详细

  1. master节点编写pod资源yaml
mkdir -p /k8s_yml/pod && cd /k8s_yml/pod
cat > /k8s_yml/pod/k8s_pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: web
spec:
  containers:
    - name: nginx
      image: 10.0.0.11:5000/nginx:1.13
      ports:
        - containerPort: 80
EOF
  1. master节点创建资源
kubectl create -f k8s_pod.yaml
  1. master节点查看所有pod资源状态(集装箱化)
[root@k8s-master pod]# kubectl get pod
NAME      READY     STATUS              RESTARTS   AGE
nginx     0/1       ContainerCreating   0          27m
  1. master节点查看指定pod资源描述(调度至10.0.0.13)
[root@k8s-master pod]# kubectl describe pod nginx
Name:		nginx
Namespace:	default
Node:		10.0.0.13/10.0.0.13
  1. node节点(10.0.0.13)搜索缺失镜像并下载,上传至私有仓库
docker search pod-infrastructure
docker pull docker.io/tianyebj/pod-infrastructure
docker tag docker.io/tianyebj/pod-infrastructure:latest 10.0.0.11:5000/pod-infrastructure:latest
docker push 10.0.0.11:5000/pod-infrastructure:latest
  1. 所有node节点修改配置文件,指定POD下载镜像地址为私有仓库,重启服务
sed -i "17c KUBELET_POD_INFRA_CONTAINER=\"--pod-infra-container-image=10.0.0.11:5000/pod-infrastructure:latest\"" /etc/kubernetes/kubelet
systemctl restart kubelet.service
  1. master节点再次查看所有pod资源状态(运行中)
[root@k8s-master pod]# kubectl get pod -o wide  # -o 显示更宽
NAME      READY     STATUS    RESTARTS   AGE       IP             NODE
nginx     1/1       Running   0          59m       172.18.100.2   10.0.0.13
  1. node节点(10.0.0.13)查看运行的容器
[root@k8s-node-2 ~]# docker ps
CONTAINER ID        IMAGE                                      COMMAND                  CREATED             STATUS              PORTS               NAMES
f4a6497de298        10.0.0.11:5000/nginx:1.13                  "nginx -g 'daemon ..."   34 minutes ago      Up 34 minutes                           k8s_nginx.91390390_nginx_default_f70dd446-3864-11eb-b602-000c295a6f81_362db3ed
8cf407292934        10.0.0.11:5000/pod-infrastructure:latest   "/pod"                   34 minutes ago      Up 34 minutes                           k8s_POD.177f01b0_nginx_default_f70dd446-3864-11eb-b602-000c295a6f81_9d56b0b4
[root@k8s-node-2 ~]# docker inspect f4a6497de298 | grep NetworkMode
            "NetworkMode": "container:8cf407292934095b3ddabecb197adb33acda43bc38a7ee73a12a681ca30a9a43",
[root@k8s-node-2 ~]# docker inspect 8cf407292934 | grep -A 1 Networks
            "Networks": {
                "bridge": {

pod资源至少由两个容器组成:基础容器pod和(多个)业务容器nginx组成,共用网络空间。

基础容器pod用于实现k8s高级功能。

  1. master节点编写pod资源yaml(两个业务容器)
cat > /k8s_yml/pod/k8s_pod2.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels:
    app: web
spec:
  containers:
    - name: nginx
      image: 10.0.0.11:5000/nginx:1.13
      ports:
        - containerPort: 80
    - name: alpine
      image: 10.0.0.11:5000/alpine:latest
      command: ["sleep","1000"]
EOF
  1. master节点创建资源
kubectl create -f k8s_pod2.yaml
  1. master节点查看所有pod资源状态
[root@k8s-master pod]# kubectl get pod
NAME      READY     STATUS    RESTARTS   AGE
nginx     1/1       Running   0          2h
test      2/2       Running   1          28m
  1. node节点(10.0.0.12)查看运行的容器(轮询负载均衡)
[root@k8s-node-1 ~]# docker ps
CONTAINER ID        IMAGE                                      COMMAND                  CREATED             STATUS              PORTS               NAMES
7bf33f049a9c        10.0.0.11:5000/alpine:latest               "sleep 1000"             11 minutes ago      Up 11 minutes                           k8s_alpine.314fe414_test_default_6ef312be-3876-11eb-bf96-000c295a6f81_48c71571
363f874e9d5a        10.0.0.11:5000/nginx:1.13                  "nginx -g 'daemon ..."   28 minutes ago      Up 28 minutes                           k8s_nginx.91390390_test_default_6ef312be-3876-11eb-bf96-000c295a6f81_f036679b
d75cc74ef792        10.0.0.11:5000/pod-infrastructure:latest   "/pod"                   28 minutes ago      Up 28 minutes                           k8s_POD.177f01b0_test_default_6ef312be-3876-11eb-bf96-000c295a6f81_96282638
[root@k8s-node-1 ~]# docker inspect 7bf33f049a9c | grep NetworkMode
            "NetworkMode": "container:d75cc74ef79284342d2c31698867a660c404f90a72170729b1f6728514efb84e",
[root@k8s-node-1 ~]# docker inspect 363f874e9d5a | grep NetworkMode
            "NetworkMode": "container:d75cc74ef79284342d2c31698867a660c404f90a72170729b1f6728514efb84e",
[root@k8s-node-1 ~]# docker inspect d75cc74ef792 | grep -A 1 Networks
#master 节点
vi k8s_pod2.yml
apiVersion: v1
kind: Pod
metadata:
  name: test
  labels:
    app: web
spec:
  containers:
    - name: nginx
      image: 10.0.0.11:5000/nginx:1.13
      ports:
        - containerPort: 80
    - name: alpine
      image: 10.0.0.11:5000/alpine:latest
      command: ["sleep","1000"]

ReplicationController资源

rc:保证指定数量的pod始终存活;

rc通过标签选择器来关联pod 不能低于5个

controller

确保周期的副本数量

无状态应用部署

有状态应用部署

确保所有的node运行同一个pod

一次性任务和定时任务

controller

在集群上管理和运行容器的对象

Pod和Controller关系

Pod通过Controller实现应用的运维,

比如伸缩,滚动升级等等

Pod和Controller之间通过label标签建立关系

selector

3.deployment应用场景

部署无状态应用

管理Pod和ReplicaSet

部署,滚动升级等功能

应用场景

web服务,微服务

4.使用deployment部署应用(yaml)

image-20201218221516794

第一步:导出yaml文件

image-20201218221624951

第二步:使用yaml部署应用

image-20201218222153712

第三步:对外发布(暴露对外端口号)

image-20201218222308441

image-20201218222332442

image-20201218222401919

1.master节点编写ReplicationController资源yaml

mkdir /k8s_yml/rc -p  && cd /k8s_yml/rc 
tee /k8s_yml/rc/k8s_rc.yml <<-EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx
spec:
  replicas: 5  #副本5
  selector:
    app: myweb
  template:  #模板
    metadata:
      labels:
        app: myweb
    spec:
      containers:
      - name: myweb
        image: 10.0.0.11:5000/nginx:1.13
        ports:
        - containerPort: 80
EOF
  1. master节点创建资源(5个pod)
kubectl create -f k8s_rc.yaml
  1. master节点查看资源状态
[root@k8s-master rc]# kubectl get rc
NAME      DESIRED   CURRENT   READY     AGE
nginx     5         5         5         6s
[root@k8s-master rc]# kubectl get pod
NAME          READY     STATUS    RESTARTS   AGE
nginx         1/1       Running   0          2h
nginx-2w6fb   1/1       Running   0          1m
nginx-35m8t   1/1       Running   0          1m
nginx-7xhms   1/1       Running   0          1m
nginx-kxljm   1/1       Running   0          1m
nginx-sv4d5   1/1       Running   0          1m
test          2/2       Running   2          38m

rc保证指定数量的pod始终存活

  1. master节点删除一个pod,再查看资源状态:仍然有5个pod
[root@k8s-master rc]# kubectl delete pod nginx-2w6fb
pod "nginx-2w6fb" deleted
[root@k8s-master rc]# kubectl get pod
NAME          READY     STATUS    RESTARTS   AGE
nginx         1/1       Running   0          2h
nginx-35m8t   1/1       Running   0          2m
nginx-5mbbq   1/1       Running   0          4s
nginx-7xhms   1/1       Running   0          2m
nginx-kxljm   1/1       Running   0          2m
nginx-sv4d5   1/1       Running   0          2m
test          2/2       Running   2          38m
[root@k8s-master rc]# kubectl get pod -o wide
NAME          READY  STATUS    RESTARTS   AGE   IP             NODE
nginx         1/1    Running   0          2h    172.18.100.2   10.0.0.13
nginx-35m8t   1/1    Running   0          6m    172.18.100.3   10.0.0.13
nginx-5mbbq   1/1    Running   0          4m    172.18.68.5    10.0.0.12
nginx-7xhms   1/1    Running   0          6m    172.18.100.4   10.0.0.13
nginx-kxljm   1/1    Running   0          6m    172.18.68.3    10.0.0.12
nginx-sv4d5   1/1    Running   0          6m    172.18.100.5   10.0.0.13
test          2/2    Running   2          43m   172.18.68.2    10.0.0.12
  1. 关闭一个node节点(10.0.0.12)(等2分钟)
systemctl stop kubelet.service
  1. master节点查看到一个node节点离线,移除该节点
[root@k8s-master rc]# kubectl get node
NAME        STATUS     AGE
10.0.0.12   NotReady   3d
10.0.0.13   Ready      3d
[root@k8s-master rc]# kubectl delete node 10.0.0.12
node "10.0.0.12" deleted
  1. master节点查看资源状态(rc资源自动迁移)
[root@k8s-master rc]# kubectl get pod -o wide
NAME          READY     STATUS    RESTARTS   AGE       IP             NODE
nginx         1/1       Running   0          2h        172.18.100.2   10.0.0.13
nginx-35m8t   1/1       Running   0          10m       172.18.100.3   10.0.0.13
nginx-7xhms   1/1       Running   0          10m       172.18.100.4   10.0.0.13
nginx-dhcxr   1/1       Running   0          7s        172.18.100.7   10.0.0.13
nginx-jqhr9   1/1       Running   0          7s        172.18.100.6   10.0.0.13
nginx-sv4d5   1/1       Running   0          10m       172.18.100.5   10.0.0.13

rc通过标签选择器来关联pod

  1. master节点删除一个pod
kubectl delete pod nginx-35m8t

使用--all参数删除所有指定种类资源

kubectl delete pod --all
  1. master节点查看标签
[root@k8s-master rc]# kubectl get pod --show-labels
NAME          READY     STATUS    RESTARTS   AGE       LABELS
nginx         1/1       Running   0          2h        app=web
nginx-7xhms   1/1       Running   0          14m       app=myweb
nginx-ccxz2   1/1       Running   0          11s       app=myweb
nginx-dhcxr   1/1       Running   0          4m        app=myweb
nginx-jqhr9   1/1       Running   0          4m        app=myweb
nginx-sv4d5   1/1       Running   0          14m       app=myweb
[root@k8s-master rc]# kubectl get rc -o wide
NAME      DESIRED   CURRENT   READY     AGE       CONTAINER(S)   IMAGE(S)                    SELECTOR
nginx     5         5         5         13m       myweb          10.0.0.11:5000/nginx:1.13   app=myweb
  1. 修改nginx的标签为app: myweb,自动删除最年轻的pod资源,保持5个
[root@k8s-master rc]# kubectl edit pod nginx
[root@k8s-master rc]# kubectl get pod --show-labels
NAME          READY     STATUS    RESTARTS   AGE       LABELS
nginx         1/1       Running   0          2h        app=myweb
nginx-7xhms   1/1       Running   0          16m       app=myweb
nginx-dhcxr   1/1       Running   0          5m        app=myweb
nginx-jqhr9   1/1       Running   0          5m        app=myweb
nginx-sv4d5   1/1       Running   0          16m       app=myweb

rc滚动升级

  1. 根据k8s_rc2.yaml创建升级k8s_rc2.yaml,修改:
    • name
    • app
    • image

1563093237250

cat > /k8s_yml/rc/k8s_rc2.yaml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx2
spec:
  replicas: 5
  selector:
    app: myweb2
  template:
    metadata:
      labels:
        app: myweb2
    spec:
      containers:
      - name: myweb2
        image: 10.0.0.11:5000/nginx:1.15
        ports:
        - containerPort: 80
EOF
  1. 升级(5s一个)
kubectl rolling-update nginx -f k8s_rc2.yaml --update-period=5s
[root@k8s-master rc]# kubectl rolling-update nginx -f k8s_rc2.yaml --update-period=5s
Created nginx2
Scaling up nginx2 from 0 to 5, scaling down nginx from 5 to 0 (keep 5 pods available, don't exceed 6 pods)
Scaling nginx2 up to 1
Scaling nginx down to 4
Scaling nginx2 up to 2
Scaling nginx down to 3
Scaling nginx2 up to 3
Scaling nginx down to 2
Scaling nginx2 up to 4
Scaling nginx down to 1
Scaling nginx2 up to 5
Scaling nginx down to 0
Update succeeded. Deleting nginx
replicationcontroller "nginx" rolling updated to "nginx2"
[root@k8s-master rc]# kubectl get pod -o wide
NAME           READY     STATUS    RESTARTS   AGE  IP             NODE
nginx2-725jx   1/1       Running   0          35s  172.18.100.6   10.0.0.13
nginx2-fhw68   1/1       Running   0          30s  172.18.100.3   10.0.0.13
nginx2-l4b5f   1/1       Running   0          50s  172.18.100.7   10.0.0.13
nginx2-r027f   1/1       Running   0          40s  172.18.100.8   10.0.0.13
nginx2-rkc14   1/1       Running   0          25s  172.18.100.2   10.0.0.13
[root@k8s-master rc]# curl -I 172.18.100.6
HTTP/1.1 200 OK
Server: nginx/1.15.5
Date: Mon, 07 Dec 2020 11:26:46 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 02 Oct 2018 14:49:27 GMT
Connection: keep-alive
ETag: "5bb38577-264"
Accept-Ranges: bytes
  1. 回滚(1s一个)
kubectl rolling-update nginx2 -f k8s_rc.yaml --update-period=1s
[root@k8s-master rc]# kubectl rolling-update nginx2 -f k8s_rc.yaml --update-period=1s
Created nginx
Scaling up nginx from 0 to 5, scaling down nginx2 from 5 to 0 (keep 5 pods available, don't exceed 6 pods)
Scaling nginx up to 1
Scaling nginx2 down to 4
Scaling nginx up to 2
Scaling nginx2 down to 3
Scaling nginx up to 3
Scaling nginx2 down to 2
Scaling nginx up to 4
Scaling nginx2 down to 1
Scaling nginx up to 5
Scaling nginx2 down to 0
Update succeeded. Deleting nginx2
replicationcontroller "nginx2" rolling updated to "nginx"
[root@k8s-master rc]# kubectl get pod -o wide
NAME          READY     STATUS    RESTARTS   AGE IP             NODE
nginx-4r223   1/1       Running   0          16s 172.18.100.4   10.0.0.13
nginx-8phch   1/1       Running   0          13s 172.18.100.3   10.0.0.13
nginx-dc8wc   1/1       Running   0          15s 172.18.100.2   10.0.0.13
nginx-kcmpv   1/1       Running   0          11s 172.18.100.5   10.0.0.13
nginx-mknrb   1/1       Running   0          9s  172.18.100.6   10.0.0.13
[root@k8s-master rc]# curl -I 172.18.100.6
HTTP/1.1 200 OK
Server: nginx/1.13.12
Date: Mon, 07 Dec 2020 11:33:03 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Mon, 09 Apr 2018 16:01:09 GMT
Connection: keep-alive
ETag: "5acb8e45-264"
Accept-Ranges: bytes

Service

service:提供服务的自动发现和负载均衡

service存在意义:

(防止pod失联)(自动发现)

image-20201218223340038

定义一组pod的访问规则(负载均衡)

image-20201218223609972

2.Pod和Service关系

image-20201218223921446

根据label和selector标签建立关联的

通过service实现Pod的负载均衡

Service三种Ip地址类型:

kubectl expose --help

NodePort 、ClusterIP、 LoadBalancer

ClusterIP:集群内部使用

NodePort: 对外访问应用使用

LoadBalancer:对外访问应用使用,公有云

node内网部署应用,外网一般不能访问到的

找到一台可以进行外网访问机器,安装nginx,反向代理

手动把可以访问节点添加到nginx里面

LoadBalancer: 公有云,把负载均衡,控制器

无状态和有状态区别

无状态:

认为Pod都是相同的

没有顺序要求

不用考虑在哪个node运行

随意进行伸缩和扩展

有状态:

上面因素都需要考虑到,

让每个pod独立的,保持pod启动顺序和唯一性

唯一的网络标识符,持久存储

有序,比如mysql主从

部署有状态应用

无头service

ClusterIP: none

(1)Statefulset 部署有状态应用

image-20201218231347460

image-20201219102209466

SatefulSet部署有状态应用必须满足类型是:StatefulSet,
clusterIP:None

查看pod有三个pod,每个都是唯一名称

image-20201218231532138

查看创建无头的service

image-20201218231645009

deployment和statefulset区别:有身份的(唯一标识的)

根据主机名+按照一定规则生成域名

每个pod有唯一主机名

唯一域名

格式: 主机名称 .service名称 名称空间.svc.cluster.local

image-20201218232036260

Pod使用RC(Replication Controller)实现高可用,会出现一些问题:

  • 只能在k8s的内部访问,客户端无法访问,因为Pod IP是私有IP地址,外界无法访问。

  • K8s中Node端口映射不可以直接映射到的Pod IP。如果一些Pod死掉了,RC就会创建一些新的Pod,新的Pod的ip地址会变化,此时做端口映射,修改规则很麻烦。

K8s使用Service资源,kube-proxy服务自动随机分配固定不变的VIP(cluster ip),VIP地址段的范围是10.254.0.0/16。Service资源帮助pod暴露端口。


  1. master节点编写service资源yaml
mkdir -p /k8s_yml/svc && cd /k8s_yml/svc
cat > /k8s_yml/svc/k8s_svc.yaml <<EOF
apiVersion: v1
kind: Service           # 简称svc
metadata:
  name: myweb
spec:
  type: NodePort        # 端口映射类型,默认ClusterIP类型
  #clusterIP:10.254.1.1
  ports:
    - port: 80          # clusterIP port
      nodePort: 30000   # node port 默认30000-32767
      targetPort: 80    # pod port
  selector:             # 选择器。当有多个Pod的时候,需要使用选择器选择为那些Pod做负载均衡。和RC一样,使用标签选择器。
    app: myweb
EOF
  1. master节点创建资源
kubectl create -f k8s_svc.yaml
  1. master节点查看所有svc资源状态
[root@k8s-master svc]# kubectl get svc
NAME         CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes   10.254.0.1     <none>        443/TCP        3d
myweb        10.254.238.3   <nodes>       80:30000/TCP   4s
[root@k8s-master svc]# kubectl describe svc
Name:			kubernetes
Namespace:		default
Labels:			component=apiserver
			provider=kubernetes
Selector:		<none>
Type:			ClusterIP
IP:			10.254.0.1
Port:			https	443/TCP
Endpoints:		10.0.0.11:6443
Session Affinity:	ClientIP
No events.


Name:			myweb
Namespace:		default
Labels:			<none>
Selector:		app=myweb
Type:			NodePort
IP:			10.254.73.4
Port:			<unset>	80/TCP
NodePort:		<unset>	30000/TCP
Endpoints:		172.18.100.2:80,172.18.100.3:80,172.18.100.4:80 + 2 more...
Session Affinity:	None
No events.
  1. master节点访问node节点端口
[root@k8s-master svc]# curl -I http://10.0.0.12:30000
HTTP/1.1 200 OK
Server: nginx/1.13.12
Date: Tue, 08 Dec 2020 01:19:56 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Mon, 09 Apr 2018 16:01:09 GMT
Connection: keep-alive
ETag: "5acb8e45-264"
Accept-Ranges: bytes

[root@k8s-master svc]# curl -I http://10.0.0.13:30000
HTTP/1.1 200 OK
Server: nginx/1.13.12
Date: Tue, 08 Dec 2020 01:19:56 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Mon, 09 Apr 2018 16:01:09 GMT
Connection: keep-alive
ETag: "5acb8e45-264"
Accept-Ranges: bytes

service提供负载均衡

  1. master节点调整rc副本数量
kubectl scale rc nginx --replicas=3
  1. master节点进入3个pod容器,修改容器的首页为不同页面
kubectl get pod
kubectl exec -it pod_name1 /bin/bash
echo 'web01' > /usr/share/nginx/html/index.html
exit
kubectl exec -it pod_name2 /bin/bash
echo 'web02' > /usr/share/nginx/html/index.html
exit
kubectl exec -it pod_name3 /bin/bash
echo 'web03' > /usr/share/nginx/html/index.html
exit

pod中有多个业务容器,使用参数--container进入指定业务容器

kubectl exec --container=alpine -it test /bin/sh
  1. master节点验证负载均衡
[root@k8s-master svc]# i=1;while ((i<=3));do curl http://10.0.0.12:30000;sleep 2;((i++));done
web02
web03
web01

service默认使用iptables实现四层负载均衡。

k8s 1.8版本推荐使用lvs(四层负载均衡 传输层tcp,udp)


service提供服务的自动发现

  1. master节点调整rc副本数量为2,查看pod
kubectl scale rc nginx --replicas=2
kubectl get pod
  1. master节点调整rc副本数量为3,查看pod
kubectl scale rc nginx --replicas=3
kubectl get pod

自定义nodePort范围

sed -i "26c KUBE_API_ARGS=\"--service-node-port-range=3000-50000\"" /etc/kubernetes/apiserver
systemctl restart kube-apiserver.service

命令行创建service资源(node端口只能随机)

kubectl expose rc nginx --type=NodePort --port=80 --target-port=80

service类型

第一种:NodePort类型

  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30008

第二种:ClusterIP类型,默认

  type: ClusterIP
  ports:
    - port: 80
      targetPort: 80

Deployment

rc在滚动升级之后,标签改变,但service却无法跟着改变,会造成服务访问中断,于是k8s引入了deployment资源。


  1. master节点编写deployment资源yaml
mkdir -p /k8s_yml/deploy && cd /k8s_yml/deploy
cat > /k8s_yml/deploy/k8s_deploy.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  strategy:              # 策略
    rollingUpdate:       # 滚动升级
      maxSurge: 1        # 多启动几个容器
      maxUnavailable: 1  # 最大不可用的pod数量
    type: RollingUpdate
  minReadySeconds: 30    # 升级间隔最小秒
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: 10.0.0.11:5000/nginx:1.13
        ports:
        - containerPort: 80
        resources:        # 资源
          limits:         # 限制
            cpu: 100m
            memory: 50Mi
          requests:
            cpu: 100m
            memory: 50Mi
EOF
  1. master节点创建资源
kubectl create -f k8s_deploy.yaml
  1. master节点查看资源状态
[root@k8s-master deploy]# kubectl get deployment
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     3         3         3            0           3s
[root@k8s-master deploy]# kubectl get pod --show-labels
NAME                     READY     STATUS    RESTARTS   AGE       LABELS
nginx-2807576163-3550z   1/1       Running   0          4s        app=nginx,pod-template-hash=2807576163
nginx-2807576163-bmxmz   1/1       Running   0          4s        app=nginx,pod-template-hash=2807576163
nginx-2807576163-pt83k   1/1       Running   0          4s        app=nginx,pod-template-hash=2807576163
nginx-8phch              1/1       Running   1          15h       app=myweb
nginx-dc8wc              1/1       Running   1          15h       app=myweb
nginx-twk24              1/1       Running   0          1h        app=myweb
[root@k8s-master deploy]# kubectl get all--

deployment滚动升级

deployment滚动升级不依赖配置文件,服务访问不中断;修改配置文件立即生效。

deployment升级时:更新了Pod,通过创建一个新的Replica Set(rc的升级版)并扩容3个replica,同时将原来的Replica Set缩容到0个replica。

下次更新这些pod的时候,只需要更新Deployment中的pod的template即可。

Deployment可以保证在升级时只有一定数量的Pod是down的。默认maxUnavailable: 1(最多一个不可用)。

Deployment同时也可以确保只创建出超过期望数量的一定数量的Pod。默认maxSurge: 1(最多1个surge)。


  1. 命令行创建service资源
kubectl expose deploy nginx --type=NodePort --port=80 --target-port=80
  1. 查看service资源映射node端口
[root@k8s-master deploy]# kubectl get svc
NAME         CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes   10.254.0.1       <none>        443/TCP        3d
myweb        10.254.73.4      <nodes>       80:30000/TCP   1h
nginx        10.254.185.133   <nodes>       80:31504/TCP   19s
  1. 升级:修改deployment配置文件。仅需要修改镜像版本
kubectl edit deployment nginx
  1. 访问验证:升级过程中新老版本可以同时访问
i=1;while ((i<=3));do curl -I 10.0.0.12:31504;sleep 1;((i++));done

deployment升级和回滚

命令行创建deployment(--record 记录版本变更原因)

kubectl run nginx --image=10.0.0.11:5000/nginx:1.13 --replicas=3 --record

命令行滚动升级版本

kubectl set image deployment nginx nginx=10.0.0.11:5000/nginx:1.15

pod中有多个业务容器,指定业务容器名称alpine=10.0.0.11:5000/alpine:1.15

查看deployment所有历史版本

kubectl rollout history deployment nginx

deployment回滚到上一个版本

kubectl rollout undo deployment nginx

deployment回滚到指定版本

kubectl rollout undo deployment nginx --to-revision=2

间章:练习

k8s中容器之间通过VIP相互访问

tomcat+mysql:2个deployment资源和2个service资源。tomcat访问mysql的svc提供的VIP

  1. node节点下载镜像,上传至私有仓库
docker pull tomcat-app:v2
docker tag docker.io/kubeguide/tomcat-app:v2 10.0.0.11:5000/tomcat-app:v2
docker push 10.0.0.11:5000/tomcat-app:v2
docker pull mysql:5.7
docker tag docker.io/mysql:5.7 10.0.0.11:5000/mysql:5.7
docker push 10.0.0.11:5000/mysql:5.7
  1. master节点创建配置文件
mkdir -p /k8s_yml/tomcat_demo && cd /k8s_yml/tomcat_demo
cat > /k8s_yml/tomcat_demo/mysql-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: 10.0.0.11:5000/mysql:5.7
          ports:
          - containerPort: 3306
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'
EOF
cat > /k8s_yml/tomcat_demo/mysql-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql
EOF
cat > /k8s_yml/tomcat_demo/tomcat-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: myweb
spec:
  replicas: 1
  selector:
    app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:
      containers:
        - name: myweb
          image: 10.0.0.11:5000/tomcat-app:v2
          ports:
          - containerPort: 8080
          env:
          - name: MYSQL_SERVICE_HOST
            value: 'mysql'
          - name: MYSQL_SERVICE_PORT
            value: '3306'
EOF
cat > /k8s_yml/tomcat_demo/tomcat-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: myweb
spec:
  type: NodePort
  ports:
    - port: 8080
      nodePort: 30008
  selector:
    app: myweb
EOF
  1. master节点创建mysql的rc和svc资源
kubectl create -f mysql-rc.yml
kubectl create -f mysql-svc.yml
  1. master节点查看所有svc资源
[root@k8s-master tomcat_demo]# kubectl get svc
NAME         CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes   10.254.0.1       <none>        443/TCP        3d
mysql        10.254.37.112    <none>        3306/TCP       18s
myweb        10.254.73.4      <nodes>       80:30000/TCP   5h
nginx        10.254.185.133   <nodes>       80:31504/TCP   3h
  1. master节点删除已有同名svc资源myweb
kubectl delete svc myweb
  1. master节点修改tomcat的rc资源配置文件,修改变量MYSQL_SERVICE_HOST的值为mysql的VIP
vim tomcat-rc.yml
  1. master节点创建tomcat的rc和svc资源
kubectl create -f tomcat-rc.yml 
kubectl create -f tomcat-svc.yml
  1. 访问:http://10.0.0.12:30008/demo/

image-20201208152415164


资源创建流程

创建pod资源流程:

  • 用户和 api-server 交互,使用创建命令 kubectl create -f .
  • api-server 检查yaml文件语法
    • 错误,报错
    • 正确写入etcd数据库
  • api-server 调用 scheduler
    • 没有可用node,Pending
    • 调度成功,返回name给api-server
  • api-server调用kubelet,发送pod配置文件

删除pod资源流程:

  • 用户和 api-server 交互,使用删除命令 kubectl delete pod nginx
  • api-server 修改etcd数据库中pod的状态
  • api-server调用kubelet停止并删除容器
    • 调用失败,Unkown
  • 调用成功,api-server删除etcd数据库中pod的记录

创建deployment资源流程:

  • 用户和 api-server 交互,使用创建命令 kubectl create -f .
  • api-server 检查yaml文件语法
    • 错误,报错
    • 正确写入etcd数据库
  • controller-manager创建rs
  • controller-manager申请创建pod
  • api-server 调用 scheduler
    • 没有可用node,Pending
    • 调度成功,返回name给api-server
  • api-server调用kubelet,发送pod配置文件

部署守护进程DaemonSet

在每个node上运行一个pod,新加入的node也同样运行在一个pod里面

例子:在每个node节点安装数据采集工具

不需要指定副本数,不需要scheduler调度,有几个node节点创建几个,适用于监控,日志收集。

注意:各资源labels不能一致!否则会导致pod一直删除再创建死循环。

mkdir -p /k8s_yml/daemonset && cd /k8s_yml/daemonset
cat > /k8s_yml/daemonset/k8s_daemonset.yaml <<EOF
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: nginx
spec:
  template:
    metadata:
      labels:
        app: oldboy
    spec:
      containers:
      - name: nginx
        image: 10.0.0.11:5000/nginx:1.13
        ports:
        - containerPort: 80
EOF
kubectl create -f k8s_daemonset.yaml
kubectl get pod -o wide

StatefulSet (PetSets)

  • StatefulSet (PetSets):宠物应用,有状态的应用,pod名称固定(有序 01 02 03),适用于数据库应用,redis,ES集群,mysql集群

  • 其他资源:畜生应用,无状态的应用,pod名称随机


Jobs

  • Jobs:一次性任务,完成状态completed
  • Pod:一直运行

image-20201219100937078


cat job.yaml
kubectl create -f job.yaml
kubectl get pods
kubectl get jobs

Cronjobs

Cronjobs:定时任务

image-20201219101516093

cat cronjob.yaml
kubectl apply -f cronjob.yaml
kubectl get pods
kubectl logs 容器名

Ingress

  • Ingress:七层负载均衡
  • Service:四层负载均衡

Secret

Secret:密码,密钥

作用:加密数据存在etcd里面,让Pod容器以挂载Volume方式进行访问

场景:凭证

echo -n 'admin'|base64

image-20201219102708049

cat secret.yaml
kubectl create -f secret.yaml
kubectl get secret

2.以变量形式挂载到容器中

image-20201219103058482


cat secret-val.yaml
kubectl create -f secret.yaml
kubectl get pods
kubectl exec -it mypod bash
echo $SECRET_USENAME
echo ¥SECRET_PASSWORD

3.以Volume形式挂载pod容器中

image-20201219110125282

cat secret-vol.yaml
kubectl  apply -f secret-vol.yaml
kubectl get pods
kubectl exec -it mypod bash
ls /etc/foo
cd /etc/foo
cat password 
cat username

Config Maps

Config Maps:配置文件

作用:存储不加密数据到etcd,让Pod以变量或者Volume挂载到容器中

场景:配置文件

1.创建配置文件

kubectl get cm

image-20201219120653459

2.创建configmap

kubectl  create configmap redis-config --from-file=redis.properties
kubectl get cs
kubectl describe cs redis-config

3.以Volume挂载到pod容器中

cat cm.yaml
kubectl apply -f cm.yaml
kubectl get pods
#出现completed状态

4.以变量形式挂载到pod容器中

(1)创建yaml,声明变量信息configmap创建

(2)以变量挂载

image-20201219121127029


cat myconfig.yaml
kubectl apply -f myconfig.yaml 
kubectl get cm 
kubectl logs mypod

k8s集群安全机制

1.概述

(1)访问k8s集群时候,需要经过三个步骤完成具体操作

第一步:认证

第二步:鉴权(授权)

第三步:准入控制

(2)进行访问时候,过程中都需要经过apiserver,apiserver做统一协调,比如门卫。

访问过程中需要证书,token,或者用户名+密码

如果访问pod需要serviceAccount

第一步认证 传输安全

传输安全: 对外不暴露8080端口,只能内部访问,对外使用端口6443

认证:

客户端身份认证常用方式:

https证书认证 基于ca证书

http token认证,通过token识别用户

http基本认证,用户名+密码认证

第二步:鉴权(授权)

基于RBAC进行鉴权操作

基于角色访问控制

第三步:准入控制

就是准入控制器的列表,如果列表有请求内容,通过,没有拒绝。

RBAC

基于角色的访问控制

角色 Role

特定命名空间访问权限

ClusterRole:所有命名空间访问权限

角色绑定

roleBinding:角色绑定到主体

ClusterRoleBinding: 集群角色绑定到主体

主体:

user 用户

group 用户组

serviceAccount 服务账号

image-20201219123648010

1.创建命名空间

kubectl create ns roledemo

2.在新创建的命名空间创建pod

kubectl run nginx --image=nginx -n roledemo

3.创建角色

cat role-rbac.yaml

image-20201219124546983

kubectl apply -f rbac-role.yaml
kubectl get role -n roledemo

4.创建角色绑定

cat rbac-rolebinding.yaml
kubectl apply -f rbac-rolebinding.yaml
kubectl get role.rolebinding -n roledemo

5.使用证书识别身份

cat rabc-user.sh
cp /root/TLS/k8s/ca* ./
bash rabc-user.sh

image-20201219131031781

Ingress

1.把端口号对外暴露,通过ip+端口号进行访问

使用service里面的NodePort实现

2.NodePort缺陷

在每个节点上都会启动端口,在访问时候通过任何节点,通过节点ip+暴露端口号实现访问

意味着每个端口只能使用一次,一个端口对应一个应用

实际访问中都是用域名,根据不同域名跳转到不同端口服务中

3.Ingress和Pod关系

pod和ingress通过service关联的

ingress作为统一入口,由service关联一组pod

ingress 入口

image-20201219134447165

4.ingress工作流程

image-20201219134743297

5.使用ingress

第一步:部署ingress Controller

第二步: 创建ingress规则

选择官方维护nginx控制器,实现部署

6.使用Ingress对外暴露应用

(1)创建nginx应用,对外暴露端口使用NodePort

kubectl create deployment web --image=nginx
kubectl get pods
kubectl get deploy
kubectl expose deployment web --port=80 --target-port=80 --type=NodePort

(2)部署ingress contronller

查看ingress controller状态

kubectl get pods -n ingress-nginx

(3)创建ingress规则

cat ingress-h.yaml
kubectl apply -f ingress-h.yaml

(4)在windows系统hosts文件中添加域名访问规则

10.0.0.11 example.ingredemo.com

helm

1.引入

(1)之前方式部署应用过程

编写yaml文件

deployment

Service

Ingress

如果使用之前方式部署单一应用,少数服务的应用,比较合适

比如部署微服务项目,可能有几十个服务,每个服务都有一套yaml文件,需要维护大量yaml文件,版本管理特别不方便;

2.使用helm能够解决的问题

(1)使用helm可以把这些yaml作为一个整体管理

(2)实现yaml高效复用

(3)使用helm应用级别的版本管理

3.helm介绍

Helm是一个Kubernetes的包管理工具,就像Linux下的包管理工具,如yum/apt等,可以很方便的将之前打包好的yaml文件部署到kubernetes上

4.Helm三个重要概念

(1)helm

是一个命令行客户端工具

(2)Chart

把yaml打包,是yaml的集合

(3)Release

基于chart部署实体,应用级别的版本管理

5.Helm v3变化

helm在2019年发布v3版本,和之前版本相比有变化

(1)V3版本删除Tiller

(2)release 可以在不同命名空间重用

(3)将chart推送到docker仓库中

6.helm架构变化

V3之前版本

image-20201219154156116

V3版本架构

image-20201219154306513

1.helm安装

第一步:下载helm安装压缩文件,上传到linux系统中

https://helm.sh/docs

wget https://github.com/helm/helm/archive/v3.4.2.tar.gz

第二步: 解压helm压缩文件,把解压之后helm目录复制到usr/bin目录下

tar xf helm-3.4.2.tar.gz
cp -r /root/helm-3.4.2 /usr/bin

2.配置helm仓库

(1)添加仓库

helm  repo  add  仓库名称  仓库地址
helm repo add 
helm repo list 

(2)更新仓库地址

helm repo update

(3)删除仓库

helm repo remove aliyun

3.helm快速部署应用

第一步: 使用命令搜索应用

helm search repo 名称  (weave)

第二步:根据搜索内容选择安装

helm install 安装之后名称   搜索之后应用名称
*  查看安装之后状态
helm list
helm status 安装之后名称
helm search repo weave
helm install ui stable/weave-scope  #安装
helm status ui

修改service的yaml文件,type改为NodePort

type: NodePort

如何自己创建Chart

1.使用命令创建chart

helm create chart 名称
helm create mychart
Chartyaml: 当前chart属性配置信息
templates: 编写yaml文件放到这个目录中
values.yaml: yaml文件可以使用全局变量

2.在templates文件夹创建两个yaml文件

deployment.yaml
service.yaml

3.安装mycat

helm install web1 mychart/

4.应用升级

helm upgrade chart名称
helm upgrade web1 mychart/

实现yaml高效复用

通过传递参数,动态渲染模板,yaml内容动态传入参数生成

values.yaml
在chart有values.yaml文件,定义yaml文件全局变量
1.在values.yaml定义变量和值
2.在具体yaml文件,获取定义变量值
yaml文件大体有几个不同的
image
tag
label
port
replicas

一.在values.yaml定义变量和值

replicas: 1

image: nginx

tag: 1.16

label: nginx

port: 80

二.在templates的yaml文件使用values.yaml定义变量

通过表达式形式使用全局变量

{{ . Values.变量名称}}

(( .Release .Name))-deploy

数据卷 emptydir,是本地存储,pod重启,数据不存在了,需要对数据持久化存储

nfs,网络存储 pod重启,数据还存在的

第一步:找一台服务器nfs服务端

(1)安装nfs

yum install nfs-utils

(2)设置挂载路径

cat /etc/exports
/data/nfs *{rw.no_root_squash}

(3)挂载路径需要创建出来

mkdir nfs

第二步 在k8s集群node节点安装nfs

yum install nfs-utils

第三步: 在nfs服务器启动nfs服务

systemctl start nfs
ps -ef | grep nfs

第四步: 在k8s集群部署应用使用nfs持久网络存储

cat nfs-nginx.yaml
kubectl apply -f nfs-nginx.yaml
kubectl get pods
kubectl describe 
kubectl exec -it nginx-名字    bash

image-20201220190059083

PV和PVC

1.PV:持久化存储,对存储资源进行抽象,对外提供可以调用的地方(生产者)

2.PVC: 用于调用,不需要关心内部实现细节(消费者)

集群资源监控

1.监控指标

集群监控

节点资源利用率

节点数

运行pods

Pod监控

容器指标

应用程序

2.监控平台搭建方案

prometheus+ Grafana   
(1)prometheus 
开源的
监控,报警,数据库
以HTTP协议周期性抓取被监控组件状态
不需要复杂的集成过程,使用http接口接入就可以了
(2)Grafana
开源的数据分析和可视化工具
支持多种数据源

image-20201220194256265

高可用:

多master

image-20201220194645422

高可用集群技术

image-20201220195133698

master1                           master2

1.部署keepalived                 1.部署keepalived 

2.部署haproxy                    2.部署haproxy

3.初始化操作                      3.添加master2节点到集群

4.安装docker,网络插件            4.安装docker,网络插件

node1节点
加入到集群中,安装docker,网络插件

资源总结

img

k8s资源 作用
daemonSet 用来描述每个宿主机上必须且只能运行一个副本的守护进程服务
Job 用来描述一次性运行的 Pod(比如,大数据任务)
CronJob 用于描述定时任务

k8s附加组件

DNS服务

DNS服务:将svc的名称解析成对应VIP地址

  1. node2节点(10.0.0.13)下载镜像,并导入(4个镜像,来自google仓库)
[root@k8s-node-2 ~]# docker load -i docker_k8s_dns.tar.gz
8ac8bfaff55a: Loading layer 1.293 MB/1.293 MB
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
b79219965469: Loading layer 45.91 MB/45.91 MB
Loaded image: gcr.io/google_containers/kubedns-amd64:1.9
3fc666989c1d: Loading layer 5.046 MB/5.046 MB
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
9eed5e14d7fb: Loading layer 348.7 kB/348.7 kB
00dc4ffe8624: Loading layer  2.56 kB/2.56 kB
Loaded image: gcr.io/google_containers/kube-dnsmasq-amd64:1.4
9007f5987db3: Loading layer  5.05 MB/5.05 MB
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
d41159f2130e: Loading layer 9.201 MB/9.201 MB
Loaded image: gcr.io/google_containers/dnsmasq-metrics-amd64:1.0
dc978cfc3e09: Loading layer 7.279 MB/7.279 MB
99740866972b: Loading layer 7.168 kB/7.168 kB
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
Loaded image: gcr.io/google_containers/exechealthz-amd64:1.2
  1. master节点创建配置文件(指定调度到node2)
mkdir -p /root/k8s_yaml/dns && cd /root/k8s_yaml/dns
cat > /root/k8s_yaml/dns/skydns-svc.yaml <<EOF
# Copyright 2016 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# TODO - At some point, we need to rename all skydns-*.yaml.* files to kubedns-*.yaml.*

# Warning: This is a file generated from the base underscore template file: skydns-svc.yaml.base

apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "KubeDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP: 10.254.230.254
  ports:
  - name: dns
    port: 53
    protocol: UDP
  - name: dns-tcp
    port: 53
    protocol: TCP
EOF
cat > /root/k8s_yaml/dns/skydns.yaml <<EOF
# Copyright 2016 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# TODO - At some point, we need to rename all skydns-*.yaml.* files to kubedns-*.yaml.*
# Should keep target in cluster/addons/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml
# in sync with this file.

# __MACHINE_GENERATED_WARNING__

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: kube-dns
  namespace: kube-system
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
spec:
  replicas: 1
  # replicas: not specified here:
  # 1. In order to make Addon Manager do not reconcile this replicas parameter.
  # 2. Default is 1.
  # 3. Will be tuned in real time if DNS horizontal auto-scaling is turned on.
  strategy:
    rollingUpdate:
      maxSurge: 10%
      maxUnavailable: 0
  selector:
    matchLabels:
      k8s-app: kube-dns
  template:
    metadata:
      labels:
        k8s-app: kube-dns
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ''
        scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly", "operator":"Exists"}]'
    spec:
      nodeName: 10.0.0.13  # 指定调度到的node
      containers:
      - name: kubedns
        image: gcr.io/google_containers/kubedns-amd64:1.9
        resources:
          # TODO: Set memory limits when we've profiled the container for large
          # clusters, then set request = limit to keep this container in
          # guaranteed class. Currently, this container falls into the
          # "burstable" category so the kubelet doesn't backoff from restarting it.
          limits:
            memory: 170Mi
          requests:
            cpu: 100m
            memory: 70Mi
        livenessProbe:
          httpGet:
            path: /healthz-kubedns
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /readiness
            port: 8081
            scheme: HTTP
          # we poll on pod startup for the Kubernetes master service and
          # only setup the /readiness HTTP server once that's available.
          initialDelaySeconds: 3
          timeoutSeconds: 5
        args:
        - --domain=cluster.local.
        - --dns-port=10053
        - --config-map=kube-dns
        - --kube-master-url=http://10.0.0.11:8080
        # This should be set to v=2 only after the new image (cut from 1.5) has
        # been released, otherwise we will flood the logs.
        - --v=0
        #__PILLAR__FEDERATIONS__DOMAIN__MAP__
        env:
        - name: PROMETHEUS_PORT
          value: "10055"
        ports:
        - containerPort: 10053
          name: dns-local
          protocol: UDP
        - containerPort: 10053
          name: dns-tcp-local
          protocol: TCP
        - containerPort: 10055
          name: metrics
          protocol: TCP
      - name: dnsmasq
        image: gcr.io/google_containers/kube-dnsmasq-amd64:1.4
        livenessProbe:
          httpGet:
            path: /healthz-dnsmasq
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        args:
        - --cache-size=1000
        - --no-resolv
        - --server=127.0.0.1 # 10053
        #- --log-facility=-
        ports:
        - containerPort: 53
          name: dns
          protocol: UDP
        - containerPort: 53
          name: dns-tcp
          protocol: TCP
        # see: https://github.com/kubernetes/kubernetes/issues/29055 for details
        resources:
          requests:
            cpu: 150m
            memory: 10Mi
      - name: dnsmasq-metrics
        image: gcr.io/google_containers/dnsmasq-metrics-amd64:1.0
        livenessProbe:
          httpGet:
            path: /metrics
            port: 10054
            scheme: HTTP
          initialDelaySeconds: 60
          timeoutSeconds: 5
          successThreshold: 1
          failureThreshold: 5
        args:
        - --v=2
        - --logtostderr
        ports:
        - containerPort: 10054
          name: metrics
          protocol: TCP
        resources:
          requests:
            memory: 10Mi
      - name: healthz
        image: gcr.io/google_containers/exechealthz-amd64:1.2
        resources:
          limits:
            memory: 50Mi
          requests:
            cpu: 10m
            # Note that this container shouldn't really need 50Mi of memory. The
            # limits are set higher than expected pending investigation on #29688.
            # The extra memory was stolen from the kubedns container to keep the
            # net memory requested by the pod constant.
            memory: 50Mi
        args:
        - --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1 >/dev/null
        - --url=/healthz-dnsmasq
        - --cmd=nslookup kubernetes.default.svc.cluster.local 127.0.0.1:10053 >/dev/null
        - --url=/healthz-kubedns
        - --port=8080
        - --quiet
        ports:
        - containerPort: 8080
          protocol: TCP
      dnsPolicy: Default  # Don't use cluster DNS.
EOF
  1. master节点创建DNS的资源
kubectl create -f .
  1. master节点检查命名空间kube-system
kubectl get namespace
kubectl get all -n kube-system -o wide
[root@k8s-master dns]# kubectl get all -n kube-system
NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deploy/kube-dns   1         1         1            1           10m

NAME           CLUSTER-IP       EXTERNAL-IP   PORT(S)         AGE
svc/kube-dns   10.254.230.254   <none>        53/UDP,53/TCP   10m

NAME                    DESIRED   CURRENT   READY     AGE
rs/kube-dns-249145955   1         1         1         10m

NAME                          READY     STATUS    RESTARTS   AGE
po/kube-dns-249145955-wdmq8   4/4       Running   0          10m
  1. 所有node节点修改kubelet配置文件,重启服务
sed -i '20c KUBELET_ARGS=\"--cluster_dns=10.254.230.254 --cluster_domain=cluster.local\"'  /etc/kubernetes/kubelet
systemctl restart kubelet
  1. master节点修改tomcat的rc资源配置文件,修改变量MYSQL_SERVICE_HOST的值为mysql,重新创建资源
cd /root/k8s_yaml/tomcat_demo
vim tomcat-rc.yml
kubectl delete -f .
kubectl create -f .
  1. master节点验证
[root@k8s-master tomcat_demo]# kubectl get pod # 查找myweb容器名
NAME                     READY     STATUS    RESTARTS   AGE
mysql-sj480              1/1       Running   0          3m
myweb-th9rx              1/1       Running   0          1m
[root@k8s-master tomcat_demo]# kubectl exec -it myweb-th9rx /bin/bash #进入容器
root@myweb-th9rx:/usr/local/tomcat# cat /etc/resolv.conf # 查看DNS解析
search default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.254.230.254
nameserver 223.5.5.5
options ndots:5
root@myweb-th9rx:/usr/local/tomcat# ping mysql # 能解析,不能ping通,VIP
PING mysql.default.svc.cluster.local (10.254.106.204): 56 data bytes
^C--- mysql.default.svc.cluster.local ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
root@myweb-th9rx:/usr/local/tomcat# exit
exit

namespace命名空间

namespace:实现资源隔离

  1. 查看命名空间
kubectl get namespace
  1. 创建命名空间
kubectl create namespace tomcat
  1. 修改配置文件指定命名空间
cd /k8s_yml/tomcat_demo/
sed -i "3a \ \ namespace: tomcat" *
yum install dos2unix -y
dos2unix *
  1. 删除所有svc和rc资源
kubectl delete svc --all
kubectl delete rc --all
  1. 创建rc和svc资源
kubectl create -f .
  1. 查看命名空间tomcat的所有资源
kubectl get all -n tomcat

注:如果出现错误

法一:将四个yml文件修改回去然后删除

kubectl delete -f .

法二:删除资源

kubectl delete svc mysql

kubectl delete svc myweb

kubectl delete rc --all

kubectl delete namespace develop 删除namespace空间

作业

k8s中容器之间通过VIP相互访问,应用DNS,namespace

wordpress+mysql:2个deployment资源和2个service资源。wordpress访问mysql的svc提供的VIP

  1. node下载镜像,上传至私有仓库
docker pull wordpress
docker tag docker.io/wordpress:latest 10.0.0.11:5000/wordpress:latest
docker push 10.0.0.11:5000/wordpress:latest
docker pull mysql:5.7
docker tag docker.io/mysql:5.7 10.0.0.11:5000/mysql:5.7
docker push 10.0.0.11:5000/mysql:5.7
  1. 创建rc和svc配置文件
mkdir -p /k8s_yml/wordpress_rc && cd /k8s_yml/wordpress_rc
cat > /k8s_yml/wordpress_rc/mysql-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  namespace: wordpress
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.12
      containers:
        - name: mysql
          image: 10.0.0.11:5000/mysql:5.7
          ports:
          - containerPort: 3306
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: 'root_pwd'
          - name: MYSQL_DATABASE
            value: 'blog'
          - name: MYSQL_USER
            value: 'blog'
          - name: MYSQL_PASSWORD
            value: 'blog'
          args:
          - --character-set-server=utf8
          - --collation-server=utf8_bin
EOF
cat > /k8s_yml/wordpress_rc/mysql-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: wordpress
  name: mysql
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql
EOF
cat > /root/k8s_yaml/wordpress_rc/wordpress-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  namespace: wordpress
  name: wordpress
spec:
  replicas: 1
  selector:
    app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      nodeName: 10.0.0.12
      containers:
        - name: wordpress
          image: 10.0.0.11:5000/wordpress:latest
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 80
          env:
          - name: WORDPRESS_DB_HOST
            value: 'mysql'
          - name: WORDPRESS_DB_PASSWORD
            value: 'blog'
          - name: WORDPRESS_DB_USER
            value: 'blog'
          - name: WORDPRESS_DB_NAME
            value: 'blog'
EOF
cat > /k8s_yml/wordpress_rc/wordpress-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: wordpress
  name: wordpress
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30080
  selector:
    app: wordpress
EOF

查看系统补全的配置文件

kubectl get pod NAME -n NAMESPACE -o yaml

镜像下载策略

[root@k8s-master ~]# kubectl explain pod.spec.containers.imagePullPo                                               licy
FIELD: imagePullPolicy <string>

DESCRIPTION:
  Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated.
  More info: http://kubernetes.io/docs/user-guide/images#updating-images
Always       总是更新镜像
Never        从不更新镜像
IfNotPresent 如果本地没有,就去pull
  1. 删除所有资源
kubectl delete svc --all
kubectl delete rc --all
kubectl delete deployment --all
  1. 创建命名空间
kubectl create namespace wordpress
  1. 创建资源
kubectl create -f .
  1. 查看svc资源,访问:http://10.0.0.12:30080/
kubectl get all -n wordpress -o wide
  1. 创建deploy和svc配置文件
mkdir -p /k8s_yml/wordpress_demo && cd /k8s_yml/wordpress_demo
cat > /k8s_yml/wordpress_demo/mysql-demo.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: wordpress
  name: mysql
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.12
      containers:
        - name: mysql
          image: 10.0.0.11:5000/mysql:5.7
          ports:
          - containerPort: 3306
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: 'root_pwd'
          - name: MYSQL_DATABASE
            value: 'blog'
          - name: MYSQL_USER
            value: 'blog'
          - name: MYSQL_PASSWORD
            value: 'blog'
          args:
          - --character-set-server=utf8
          - --collation-server=utf8_bin
EOF
cat > /k8s_yml/wordpress_demo/mysql-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: wordpress
  name: mysql
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql
EOF
cat > /k8s_yml/wordpress_demo/wordpress-demo.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: wordpress
  name: wordpress
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      nodeName: 10.0.0.12
      containers:
        - name: wordpress
          image: 10.0.0.11:5000/wordpress:latest
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 80
          env:
          - name: WORDPRESS_DB_HOST
            value: 'mysql'
          - name: WORDPRESS_DB_PASSWORD
            value: 'blog'
          - name: WORDPRESS_DB_USER
            value: 'blog'
          - name: WORDPRESS_DB_NAME
            value: 'blog'
EOF
cat > /k8s_yml/wordpress_demo/wordpress-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: wordpress
  name: wordpress
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30080
  selector:
    app: wordpress
EOF

wordpress-mysql基于rc书写

docker run --name mysql-wp -it \
      -e MYSQL_DATABASE="blog" \
      -e MYSQL_USER="blog" \
      -e MYSQL_PASSWORD="blog" \
      -e MYSQL_ROOT_PASSWORD="root_pwd" \
      -d docker.io/mysql:5.7 \
      --character-set-server=utf8 --collation-server=utf8_bin
	  
docker run --name wordpress  -p 81:80 --link mysql-wp:mysql -e WORDPRESS_DB_HOST=mysql \
    -e WORDPRESS_DB_USER=blog 
    -e WORDPRESS_DB_NAME=blog 
    -e WORDPRESS_DB_PASSWORD=blog 
    -d docker.io/wordpress:latest
wget http://192.168.15.253/docker_images/wordpress-latest.tar.gz
docker load -i wordpress-latest.tar.gz
docker tag docker.io/wordpress:latest 10.0.0.11:5000/wordpress:latest
docker push 10.0.0.11:5000/wordpress:latest

法一:

rm -rf tomcat_demo
cp -a tomcat wordpress/
rename tomcat wordpress *  #修改所有的tomcat为wordpress 
cd wordpress 

法二:

mkdir /k8s_yml/wordpress_demo  && cd /k8s_yml/wordpress_demo
kubectl create namespace wordpress
kubectl create -f .
cat > /k8s_yml/wordpress_demo/mysql-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  namespace: wordpress
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
    nodeName: 10.0.0.13
    containers:        
        - name: mysql
          image: 10.0.0.11:5000/mysql:5.7
          ports:
          - containerPort: 3306
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: 'root_pwd'
          - name: MYSQL_DATABASE
            value: 'blog'
          - name: MYSQL_USER
            value: 'blog'
          - name: MYSQL_PASSWORD
            value: 'blog'
          args:
          - --character-set-server=utf8
          - --collation-server=utf8_bin
EOF

cat > /k8s_yml/wordpress_demo/mysql-svc.yml <<EOF
kind: Service
metadata:
  namespace: wordpress
  name: mysql
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql
EOF   


cat > /k8s_yml/wordpress_demo/wordpress-rc.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  namespace: wordpress
  name: wordpress
spec:
  replicas: 1
  selector:
    app: wordpress
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      nodeName: 10.0.0.13
      containers:
        - name: wordpress
          image: 10.0.0.11:5000/wordpress:latest
imagePullPolicy:  IfNotPresent
          ports:
          - containerPort: 80
          env:
          - name: WORDPRESS_DB_HOST
            value: 'mysql'
          - name: WORDPRESS_DB_PASSWORD
            value: 'blog'
          - name: WORDPRESS_DB_USER
            value: 'blog'
          - name: WORDPRESS_DB_NAME
            value: 'blog'
EOF


cat > /k8s_yml/wordpress_demo/wordpress-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: wordpress
  name: wordpress
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30006
  selector:
    app: wordpress
EOF    

kubectl get all -n  wordpress

wordpress-mysql基于deploy的书写

kubectl delete -f .
rename rc deploy *
tee /k8s_yml/wordpress_demo/mysql-deploy.yml<<-EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: wordpress
  name: mysql
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.13
      containers:
        - name: mysql
          image: 10.0.0.11:5000/mysql:5.7
          ports:
          - containerPort: 3306
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: 'root_pwd'
          - name: MYSQL_DATABASE
            value: 'blog'
          - name: MYSQL_USER
            value: 'blog'
          - name: MYSQL_PASSWORD
            value: 'blog'
          args:
          - --character-set-server=utf8
          - --collation-server=utf8_bin
EOF

tee /k8s_yml/wordpress_demo/wordpress-deploy.yml <<-EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: wordpress
  name: wordpress
spec:
  replicas: 1
  template:  
    metadata:
      labels:
        app: wordpress
    spec:
      nodeName: 10.0.0.13
      containers:
        - name: wordpress
          image: 10.0.0.11:5000/wordpress:latest
          ports:
          - containerPort: 80
          env:
          - name: WORDPRESS_DB_HOST
            value: 'mysql'
          - name: WORDPRESS_DB_PASSWORD
            value: 'blog'
          - name: WORDPRESS_DB_USER
            value: 'blog'
          - name: WORDPRESS_DB_NAME
            value: 'blog'
EOF



kubectl create -f .
kubectl get all -n wordpress -o wide

注:快捷键操作

ndd

dw 快速切换到一整行的行尾 /HOME

行首 /END

健康检查和可用性检查

探针的种类

livenessProbe:健康状态检查,周期性检查服务是否存活,检查结果失败,将重启容器

readinessProbe:可用性检查,周期性检查服务是否可用,不可用将从service的endpoints中移除

探针的检测方法

  • exec:执行一段命令 返回值为0正常, 非0不正常
  • httpGet:检测某个 http 请求的返回状态码 2xx,3xx正常, 4xx,5xx错误
  • tcpSocket:测试某个端口是否能够连接

liveness探针的exec使用

mkdir /k8s_yml/check/ -p && cd /k8s_yml/check
tee  /k8s_yml/check/nginx_pod_exec.yaml <<-EOF
iapiVersion: v1
kind: Pod
metadata:
  name: exec
spec:
  containers:
    - name: nginx
      image: 10.0.0.11:5000/nginx:1.13
      ports:
        - containerPort: 80
      args:
        - /bin/sh
        - -c
        - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
      livenessProbe:  # 模拟健康检查,启动后30s内健康,之后不健康
        exec:
          command:
            - cat
            - /tmp/healthy
        initialDelaySeconds: 5  #初始化5秒后开始检查  
        periodSeconds: 5        #检查周期5秒一次
        timeoutSeconds: 3       #检查命令超时时间,默认1s
        successThreshold: 1     #检查成功1次就算成功,默认1次
        failureThreshold: 1     # 检查失败1次就算失败,默认3次
EOF
kubectl create -f .
kubectl get pod -o yaml
name: exec
    namespace: default  默认指定namespace空间

注:

  •      args:
           - /bin/sh
           - -c
           - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    

    等价
    bin/sh -c "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"

    mysqladmin ping  # 检测mysql存活
    

liveness探针的httpGet使用

mkdir /k8s_yml/check/ -p && cd /k8s_yml/check
tee  nginx_pod_httpGet.yaml <<-EOF
iapiVersion: v1
kind: Pod
metadata:
  name: httpget
spec:
  containers:
    - name: nginx
      image: 10.0.0.11:5000/nginx:1.13
      ports:
        - containerPort: 80
      livenessProbe:
        httpGet:
          path: /index.html
          port: 80
        initialDelaySeconds: 3
        periodSeconds: 3
EOF
kubectl create -f nginx_pod_httpGet.yaml
kubectl describe pod httpget
kubectl exec -it httpget /bin/bash
rm -f /usr/share/nginx/html/index/html
exit
kubectl describe pod httpget

liveness探针的tcpSocket使用

mkdir /k8s_yml/check/ -p && cd /k8s_yml/check
tee  /k8s_yml/check/nginx_pod_tcpSocket.yaml<<-EOF
iapiVersion: v1
kind: Pod
metadata:
  name: tcpSocket
spec:
  containers:
    - name: nginx
      image: 10.0.0.11:5000/nginx:1.13
      ports:
        - containerPort: 80
      args:
        - /bin/sh
        - -c
        - tail -f /etc/hosts
      livenessProbe:
        tcpSocket:
          port: 80
        initialDelaySeconds: 10
        periodSeconds: 3 
EOF
kubectl create -f nginx_pod_tcpSocket.yaml
kubectl describe pod tcpsocket
kubectl exec -it tcpsocket /bin/bash
nginx -s stop
exit
kubectl describe pod tcpsocket
exec:    redis info  适合于不适合web界面的业务
httpget: web服务

readiness探针的httpGet使用

mkdir /k8s_yml/check/ -p && cd /k8s_yml/check
vi  /k8s_yml/check/nginx-rc-httpGet.yaml
iapiVersion: v1
kind: ReplicationController
metadata:
  name: readiness
spec:
  replicas: 2
  selector:
    app: readiness
  template:
    metadata:
      labels:
        app: readiness
    spec:
      containers:
      - name: readiness
        image: 10.0.0.11:5000/nginx:1.13
        ports:
        - containerPort: 80
        readinessProbe:
          httpGet:
            path: /qiangge.html
            port: 80
          initialDelaySeconds: 3
          periodSeconds: 3



readiness  
web服务
httpget
kubectl create -f nginx-rc-httpGet.yaml
kubectl get rc
kubectl get pod
kubectl expose rc readiness --type=NodePort --port=80 --target-port=80
#加入server服务
echo 'web01' > /usr/share/nginx/html/qiangge.html
exit
kubectl get pod
kubectl describe svc readiness       

部署Dashboard服务

  1. node2节点(10.0.0.13)下载镜像,并导入,打标(来自tenxcloud仓库)
[root@k8s-node-2 opt]# docker load -i kubernetes-dashboard-amd64_v1.4.1.tar.gz 
5f70bf18a086: Loading layer 1.024 kB/1.024 kB
2e350fa8cbdf: Loading layer 86.96 MB/86.96 MB
Loaded image: index.tenxcloud.com/google_containers/kubernetes-dashboard-amd64:v1.4.1
[root@k8s-node-2 opt]# docker tag index.tenxcloud.com/google_containers/kubernetes-dashboard-amd64:v1.4.1 10.0.0.11:5000/kubernetes-dashboard-amd64:v1.4.1
  1. master节点创建配置文件(指定调度到node2)
mkdir -p /root/k8s_yaml/dashboard/ && cd /root/k8s_yaml/dashboard/
cat > /root/k8s_yaml/dashboard/dashboard.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
# Keep the name in sync with image version and
# gce/coreos/kube-manifests/addons/dashboard counterparts
  name: kubernetes-dashboard-latest
  namespace: kube-system
spec:
  replicas: 1
  template:
    metadata:
      labels:
        k8s-app: kubernetes-dashboard
        version: latest
        kubernetes.io/cluster-service: "true"
    spec:
      nodeName: 10.0.0.13  # 指定调度到的node
      containers:
      - name: kubernetes-dashboard
        image: 10.0.0.11:5000/kubernetes-dashboard-amd64:v1.4.1
        resources:
          # keep request = limit to keep this container in guaranteed class
          limits:
            cpu: 100m
            memory: 50Mi
          requests:
            cpu: 100m
            memory: 50Mi
        ports:
        - containerPort: 9090
        args:
         -  --apiserver-host=http://10.0.0.11:8080
        livenessProbe:
          httpGet:
            path: /
            port: 9090
          initialDelaySeconds: 30
          timeoutSeconds: 30
EOF
cat > /root/k8s_yaml/dashboard/dashboard-svc.yaml <<EOF
apiVersion: v1
kind: Service
metadata:
  name: kubernetes-dashboard
  namespace: kube-system
  labels:
    k8s-app: kubernetes-dashboard
    kubernetes.io/cluster-service: "true"
spec:
  selector:
    k8s-app: kubernetes-dashboard
  ports:
  - port: 80
    targetPort: 9090
EOF
  1. master节点创建dashboard的资源
kubectl create -f .
  1. master节点检查命名空间kube-system
kubectl get all -n kube-system
  1. 访问http://10.0.0.11:8080/ui/

全局资源

  • Namespaces
  • Nodes
  • Persistemt Volume Claims

局部资源(各Namespaces分别使用的资源)

daemonsets

daemonset的应用场景: 刚好一个node节点只需要跑一个服务的应用

daemonset: 不需要指定副本数,不需要scheduler调度

监控   node-exporter  3个计算节点  deployment  scale调度

mkdir /k8s_yml/daemonset && cd /k8s_yml/daemonset 
 tee k8s_daemon.yml <<-EOF
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: nginx
spec:
  template:
    metadata:
      labels:
        app: oldboy    #更改标签
    spec:
      containers:
      - name: nginx
        image: 10.0.0.11:5000/nginx:1.13
        ports:
        - containerPort: 80
EOF

  kubectl create -f  k8s_daemon.yml
  kubectl get pod -o wide
  kubectl get pod

注:标签不要相同

pet sets:宠物应用  有状态的应用  pod名字固定 01 02 03
其他: 畜生应用     无状态的应用  pod名字随机
statsfulset:数据库的应用  redis esj集群 mysql
jobs: 一次性任务 complete
pod: 一直运行
cronjobs:     定时任务
service:     四层负载均衡
ingresses:   七层负载均衡
pvc和pv   存储
config   配置
secret: 密码,秘钥
config maps:配置文件

通过api-server反向代理访问service

  1. 分析dashboard服务web页面

    主页+锚点(#)

http://10.0.0.11:8080/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard/#/workload?namespace=default
  1. 查看所有命名空间的svc
kubectl get svc --all-namespaces
  1. 通过apiservice反向代理访问service资源
http://10.0.0.11:8080/api/v1/proxy/namespaces/命名空间名称/services/service名称/

弹性伸缩

Kubernetes HPA(Horizontal Pod Autoscaler)Pod 水平自动扩缩:可以基于 CPU 利用率自动扩缩 ReplicationController、Deployment、ReplicaSet 和 StatefulSet 中的 Pod 数量。 除了 CPU 利用率,也可以基于其他应程序提供的自定义度量指标来执行自动扩缩。 但不适用于无法扩缩的对象,比如 DaemonSet。

Pod 水平自动扩缩特性由 Kubernetes API 资源和控制器实现。资源决定了控制器的行为。 控制器会周期性的调整副本控制器或 Deployment 中的副本数量,以使得 Pod 的平均 CPU 利用率与用户所设定的目标值匹配。

Pod水平自动伸缩:

  • 1.11版本之前,依赖heapster监控各node节点信息。
  • 1.11版本之后,使用Horizontal Pod Autoscaling资源

HPA工作机制

image-20201209191303685

安装heapster监控

k8s原生集群监控方案(Heapster+InfluxDB+Grafana+Dashboard) :

Heapster处理数据储存到InfluxDB,Grafana从InfluxDB读取数据出图,Dashboard调用Grafana的图。

image-20201209194647502

1.node2节点(10.0.0.13)下载镜像,并导入,打标**(3个镜像,来自官方仓库)

ls *.tar.gz
for n in `ls *.tar.gz`;do docker load -i $n ;done
docker tag docker.io/kubernetes/heapster_grafana:v2.6.0 10.0.0.11:5000/heapster_grafana:v2.6.0
docker tag  docker.io/kubernetes/heapster_influxdb:v0.5 10.0.0.11:5000/heapster_influxdb:v0.5
docker tag docker.io/kubernetes/heapster:canary 10.0.0.11:5000/heapster:canary

2.master节点创建配置文件(指定调度到node2)

mkdir /k8s_yml/heapster && cd /k8s_yml/heapster
rz heapster-influxdb.zip
mv heapster-influxdb/* .
rm -rf heapster-influxdb
tee /k8s_yml/heapster/heapster-controller.yaml <<-EOF
apiVersion: v1
kind: ReplicationController
metadata:
  labels:
    k8s-app: heapster
    name: heapster
    version: v6
  name: heapster
  namespace: kube-system
spec:
  replicas: 1
  selector:
    k8s-app: heapster
    version: v6
  template:
    metadata:
      labels:
        k8s-app: heapster
        version: v6
    spec:
      nodeName: 10.0.0.13   # 指定调度到的node
      containers:
      - name: heapster
        image: 10.0.0.11:5000/heapster:canary
        #imagePullPolicy: Always
        command:
        - /heapster
        - --source=kubernetes:http://10.0.0.11:8080?inClusterConfig=false
        - --sink=influxdb:http://monitoring-influxdb:8086
EOF


tee /k8s_yml/heapster/influxdb-grafana-controller.yaml <<-EOF   
apiVersion: v1
kind: ReplicationController
metadata:
  labels:
    name: influxGrafana
  name: influxdb-grafana
  namespace: kube-system
spec:
  replicas: 1
  selector:
    name: influxGrafana
  template:
    metadata:
      labels:
        name: influxGrafana
    spec:
      nodeName: 10.0.0.13
      containers:
      - name: influxdb
        image: 10.0.0.11:5000/heapster_influxdb:v0.5
        volumeMounts:
        - mountPath: /data
          name: influxdb-storage
      - name: grafana
        image: 10.0.0.11:5000/heapster_grafana:v2.6.0
        env:
          - name: INFLUXDB_SERVICE_URL
            value: http://monitoring-influxdb:8086
            # The following env variables are required to make Grafana accessible via
            # the kubernetes api-server proxy. On production clusters, we recommend
            # removing these env variables, setup auth for grafana, and expose the grafana
            # service using a LoadBalancer or a public IP.
          - name: GF_AUTH_BASIC_ENABLED
            value: "false"
          - name: GF_AUTH_ANONYMOUS_ENABLED
            value: "true"
          - name: GF_AUTH_ANONYMOUS_ORG_ROLE
            value: Admin
          - name: GF_SERVER_ROOT_URL
            value: /api/v1/proxy/namespaces/kube-system/services/monitoring-grafana/
        volumeMounts:
        - mountPath: /var
          name: grafana-storage
      volumes:
      - name: influxdb-storage
        emptyDir: {}
      - name: grafana-storage
        emptyDir: {}
EOF     
  1. master节点创建dashboard的资源
kubectl create -f .
  1. master节点检查命名空间kube-system,查看集群信息
kubectl get all -n kube-system
kubectl cluster-info
  1. 浏览器访问dashboard验证http://10.0.0.11:8080/ui/

image-20201209163521407

  1. 可以使用top命令
kubectl top node

弹性伸缩

HPA YAML默认文件

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  creationTimestamp: 2017-06-29T08:04:08Z
  name: nginxtest
  namespace: default
  resourceVersion: "951016361"
  selfLink: /apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/nginxtest
  uid: 86febb63-5ca1-11e7-aaef-5254004e79a3
spec:
  maxReplicas: 5 //资源最大副本数
  minReplicas: 1 //资源最小副本数
  scaleTargetRef:
    apiVersion: extensions/v1beta1
    kind: Deployment //需要伸缩的资源类型
    name: nginxtest  //需要伸缩的资源名称
  targetCPUUtilizationPercentage: 50 //触发伸缩的cpu使用率
status:
  currentCPUUtilizationPercentage: 48 //当前资源下pod的cpu使用率
  currentReplicas: 1 //当前的副本数
  desiredReplicas: 2 //期望的副本数
  lastScaleTime: 2017-07-03T06:32:19Z

1.master节点创建测试Deployment和svc资源

cd /root/k8s_yaml/deploy
cat > /root/k8s_yaml/deploy/k8s_deploy2.yaml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: 10.0.0.11:5000/nginx:1.13
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 100m
            memory: 50Mi
          requests:
            cpu: 100m
            memory: 50Mi
EOF
kubectl create -f k8s_deploy2.yaml
kubectl expose deploy nginx --type=NodePort --port=80 --target-port=80
  1. 创建弹性伸缩规则
kubectl autoscale deploy nginx --max=8 --min=1 --cpu-percent=5
  1. 查看hpa资源,nginx访问地址IP:PORT
kubectl get all -o wide
  1. 查看hpa资源配置文件
kubectl get hpa nginx -o yaml
  1. 压测
yum install httpd-tools -y
ab -n 1000000 -c 40 http://10.0.0.12:32114/index.html
  1. 验证http://10.0.0.11:8080/ui/

压测前:

image-20201209172019380

压测10s后,自动扩容

image-20201209172134559

停止压测5分钟后,自动缩容:

image-20201209172743894

emptyDir+tomcat

kubectl get pod -n tomcat -o wide
kubectl exec -n tomcat -it mysql-8ltcq  /bin/bash
mysql -uroot -p123456
kubectl explain pod.spec.containers
kubectl explain pod.spec.containers.volumeMounts 
kubectl explain pod.spec.volumes   #查看volumes帮助

a.master节点创建emptyDir持久化配置文件

tee /k8s_yml/tomcat_demo/mysql-emptyDir.yml <<-EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.12
      volumes:
      - name: mysql
        emptyDir: {}
      containers:
        - name: wp-mysql
          image: 10.0.0.11:5000/mysql:5.7
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 3306
          volumeMounts:
          - mountPath: /var/lib/mysql
            name: mysql
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'
EOF

b.master节点删除原rc资源,创建emptyDir持久化的rc资源

kubectl delete -f mysql-rc.yml
kubectl create -f mysql-emptyDir.yml

c.node节点查看临时目录

ll /var/lib/kubelet/pods/
ll /var/lib/kubelet/pods/sha256号/volumes/kubernetes.io~empty-dir/mysql

持久化存储

为了保证数据不丢失

查看持久化计划信息

kubectl explain pod.spec.containers.volumeMounts
kubectl explain pod.spec.volumes

持久化存储类型:

  • emptyDir:共享pod生存期的临时目录。
  • hostPath:主机上预先存在的文件或目录直接公开给容器。这通常用于允许查看主机的系统代理或其他特权对象。
  • nfs:共享pod生存期的NFS装载。

emptyDir

临时的空目录:伴随pod的生命周期,随着pod删除而删除,数据持久化但不共享。

适用于存放日志(pod之间不同,但需要保存的数据)。

emptyDir是一种临时存储,pod创建的时候会在node节点上为容器申请一个临时的目录,跟随容器的生命周期,若容器删除,emptyDir定义的临时存储空间也会随之删除,容器发生意外crash则不受影响,同时如果容器发生了迁移,其上的数据也会丢失,emptyDir一般用于测试,或者缓存场景。注意:容器崩溃不会导致数据的丢失,因为容器的崩溃并不移除pod.

emptyDir 的一些用途:

  • 缓存空间,例如基于磁盘的归并排序。
  • 为耗时较长的计算任务提供检查点,以便任务能方便地从崩溃前状态恢复执行。
  • 在 Web 服务器容器服务数据时,保存内容管理器容器获取的文件。

image-20201210135509124


  1. 创建tomcat+mysql的资源
cd /root/k8s_yaml/tomcat_demo && kubectl create -f .
  1. 访问:http://10.0.0.12:30008/demo/,添加数据
  2. node节点清空容器,虽然会重启一批容器,但之前添加的数据没了,因此需要持久化存储
docker rm -f `docker ps -aq`
  1. master节点创建emptyDir持久化配置文件
cat > /k8s_yml/tomcat_demo/mysql-emptyDir.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.12
      volumes:
      - name: mysql
        emptyDir: {}
      containers:
        - name: wp-mysql
          image: 10.0.0.11:5000/mysql:5.7
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 3306
          volumeMounts:
          - mountPath: /var/lib/mysql
            name: mysql
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'
EOF
  1. master节点删除原rc资源,创建emptyDir持久化的rc资源
kubectl delete -f mysql-rc.yml
kubectl create -f mysql-emptyDir.yml
  1. node节点查看临时目录
ll /var/lib/kubelet/pods/
ll /var/lib/kubelet/pods/sha256号/volumes/kubernetes.io~empty-dir/mysql

删除pod,这个文件也会自动删除。


HostPath

HostPath:可以多个容器共享持久化数据,但不能跨宿主机。

表示主机上预先存在的文件或目录直接暴露在容器中。
可以实现数据共享存储;

hostPath 卷能将node宿主机节点文件系统上的文件或目录挂载到您的 Pod 中。

  • 运行一个需要访问 Docker 引擎内部机制的容器;请使用 hostPath 挂载 /var/lib/docker 路径。
  • 在容器中运行 cAdvisor 时,以 hostPath 方式挂载 /sys
  • 允许 Pod 指定给定的 hostPath 在运行 Pod 之前是否应该存在,是否应该创建以及应该以什么方式存在。

使用这种类型的卷时要小心,因为:

  • 具有相同配置(例如从 podTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。
  • 当 Kubernetes 按照计划添加资源感知的调度时,这类调度机制将无法考虑由 hostPath 使用的资源。
  • 基础主机上创建的文件或目录只能由 root 用户写入。您需要在特权容器中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。

  1. master节点创建wordpress+mysql资源
cd /k8s_yml/wordpress_demo
kubectl create namespace wordpress
kubectl create -f .
  1. master节点持久化mysql
cat > /k8s_yml/wordpress_demo/mysql-demo.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: wordpress
  name: mysql
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.12
      volumes:
      - name: mysql
        emptyDir: {}
      containers:
        - name: mysql
          image: 10.0.0.11:5000/mysql:5.7
          volumeMounts:
          - mountPath: /var/lib/mysql
            name: mysql
          ports:
          - containerPort: 3306
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: 'root_pwd'
          - name: MYSQL_DATABASE
            value: 'blog'
          - name: MYSQL_USER
            value: 'blog'
          - name: MYSQL_PASSWORD
            value: 'blog'
          args:
          - --character-set-server=utf8
          - --collation-server=utf8_bin
EOF
  1. master节点应用配置文件:新建一个资源,此次不适用
kubectl apply -f mysql-demo.yml
kubectl get pod -o wide -n wordpress
kubectl delete deploy -n wordpress --all
kubectl create -f mysql-demo.yml
kubectl create -f wordpress-demo.yml
  1. master节点持久化wordpress
cat > /k8s_yml/wordpress_demo/wordpress-demo.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: wordpress
  name: wordpress
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: wordpress
    spec:
      nodeName: 10.0.0.12
      volumes:
      - name: wp-code
        hostPath:
          path: /data/wp-code
      containers:
        - name: wordpress
          image: 10.0.0.11:5000/wordpress:latest
          imagePullPolicy: IfNotPresent
          volumeMounts:
          - name: wp-code
            mountPath: /var/www/html
          ports:
          - containerPort: 80
          env:
          - name: WORDPRESS_DB_HOST
            value: 'mysql'
          - name: WORDPRESS_DB_PASSWORD
            value: 'blog'
          - name: WORDPRESS_DB_USER
            value: 'blog'
          - name: WORDPRESS_DB_NAME
            value: 'blog'
EOF
  1. master节点替换配置文件,删除所有pod生效
mkdir -p /data/wp-code
kubectl replace -f wordpress-demo.yml
kubectl delete pod -n wordpress --all 
kubectl get pod -o wide -n wordpress
  1. 安装wordpresshttp://10.0.0.13:30006/

  2. node2(10.0.0.13)节点查看持久化目录

ll /data/wp-code
  1. wordpress上传图片

  2. node2查看上传图片

ll /data/wp-code/wp-content/uploads/

删除pod时,文件不会删除掉,还要保存到node上。

  1. master节点修改副本数
kubectl scale -n wordpress deployment wordpress --replicas=2
  1. master节点查看pod资源
kubectl get pod -o wide -n wordpress
  1. node2创建phpinfo页面
echo "<?php phpinfo() ?>" > /data/wp-code/info.php
  1. 访问phpinfo页面,验证调度到多个pod,但共享数据
curl 10.0.0.12:30006/info.php | grep -i 172.18.98

NFS

NFS:可以多个容器跨宿主机共享持久化数据。

  1. 所有节点安装nfs-utils
yum -y install nfs-utils
  1. master节点部署nfs服务
mkdir -p /data/tomcat-db
cat > /etc/exports <<EOF
/data    10.0.0.0/24(rw,sync,no_root_squash,no_all_squash)
EOF
systemctl restart rpcbind
systemctl restart nfs
  1. 所有node节点检查挂载
showmount -e 10.0.0.11
  1. master节点创建nfs持久化配置文件
cd /root/k8s_yaml/tomcat_demo
cat > /k8s_yml/tomcat_demo/mysql-emptyDir.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      volumes:
      - name: mysql
        nfs:
          path: /data/tomcat-db
          server: 10.0.0.11
      containers:
        - name: wp-mysql
          image: 10.0.0.11:5000/mysql:5.7
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 3306
          volumeMounts:
          - mountPath: /var/lib/mysql
            name: mysql
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'
EOF
  1. master节点替换配置文件,删除所有pod生效
kubectl create -f  mysql-emptyDir.yml
kubectl replace -f mysql-emptyDir.yml
kubectl delete pod --all
kubectl get pod -o wide
  1. node1查看nfs挂载
df -Th|grep nfs
  1. 访问:http://10.0.0.12:30006/demo/,添加数据

  2. master节点修改配置文件:调度到13上

cat > /k8s_yml/tomcat_demo/mysql-emptyDir.yml <<EOF
apiVersion: v1
kind: ReplicationController
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.13
      volumes:
      - name: mysql
        nfs:
          path: /data/tomcat-db
          server: 10.0.0.11
      containers:
        - name: wp-mysql
          image: 10.0.0.11:5000/mysql:5.7
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 3306
          volumeMounts:
          - mountPath: /var/lib/mysql
            name: mysql
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'
EOF
  1. master节点替换配置文件,删除所有pod生效
kubectl replace -f mysql-emptyDir.yml
kubectl delete pod --all
kubectl get pod -o wide
  1. node2查看nfs挂载
df -Th|grep nfs
  1. 访问:http://10.0.0.13:30008/demo/,数据还在

PV和PVC

PersistentVolume(持久化卷):全局资源,是对底层的共享存储的一种抽象。PV 由管理员进行创建和配置,它和具体的底层的共享存储技术的实现方式有关,比如 Ceph、GlusterFS、NFS 等,都是通过插件机制完成与共享存储的对接。

PersistentVolumeClaim(持久化卷声明):局部资源,属于某一个namespace。PVC 是用户存储的一种声明,PVC 和 Pod 比较类似,Pod 消耗的是节点,PVC 消耗的是 PV 资源,Pod 可以请求 CPU 和内存,而 PVC 可以请求特定的存储空间和访问模式。对于真正使用存储的用户不需要关心底层的存储实现细节,只需要直接使用 PVC 即可。

img

  • Volumes:最基础的存储抽象,其支持多种类型,包括本地存储、NFS、FC以及众多的云存储,我们也可以编写自己的存储插件来支持特定的存储系统。Volume可以被Pod直接使用,也可以被PV使用。普通的Volume和Pod之间是一种静态的绑定关系,在定义Pod的同时,通过volume属性来定义存储的类型,通过volumeMount来定义容器内的挂载点。
  • PersistentVolume:是Kubernetes中的一个资源对象,创建一个PV相当于创建了一个存储资源对象,这个资源的使用要通过PVC来请求。
  • PersistentVolumeClaim:是用户对存储资源PV的请求,根据PVC中指定的条件Kubernetes动态的寻找系统中的PV资源并进行绑定。目前PVC与PV匹配可以通过StorageClassName、matchLabels或者matchExpressions三种方式。
  • StorageClass:存储类,目前kubernetes支持很多存储,例如ceph,nfs。glusterfs等。

生命周期

PV是集群中的资源。PVC是对这些资源的请求,也是对资源的索赔检查。 PV和PVC之间的相互作用遵循这个生命周期:Provisioning ——-> Binding ——–>Using——>Releasing——>Recycling

img

PVC 处理流程

图片.png


Provisioning

PV的提供方式:静态或者动态。

  • Static:集群管理员创建多个PV。 它们携带可供集群用户使用的真实存储的详细信息。 它们存在于Kubernetes API中,可用于消费。
  • Dynamic:当管理员创建的静态PV都不匹配用户的PersistentVolumeClaim时,集群可能会尝试为PVC动态配置卷。 此配置基于StorageClasses:PVC必须请求一个类,并且管理员必须已创建并配置该类才能进行动态配置。 要求该类的声明有效地为自己禁用动态配置。

Provisioning


PV访问模式

  • RWO - ReadWriteOnce——该卷可以被单个节点以读/写模式挂载
  • ROX - ReadOnlyMany——该卷可以被多个节点以只读模式挂载
  • RWX - ReadWriteMany——该卷可以被多个节点以读/写模式挂载

zp7dytnfgz


  1. master节点创建svc配置文件
mkdir -p /k8s_yml/volume && cd /k8s_yml/volume
cat > /k8s_yml/volume/mysql-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: tomcat
  name: mysql
spec:
  ports:
    - port: 3306
      targetPort: 3306
  selector:
    app: mysql
EOF


cat > /k8s_yml/volume/tomcat-svc.yml <<EOF
apiVersion: v1
kind: Service
metadata:
  namespace: tomcat
  name: myweb
spec:
  type: NodePort
  ports:
    - port: 8080
      nodePort: 30008
  selector:
    app: myweb
EOF
  1. master节点创建pv配置文件
 mkdir -p /data/pv{1,2,3}
cat > /k8s_yml/volume/pv1.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
  labels:
    type: nfs001
spec:
  capacity:
    storage: 10Gi                         # 不会去验证是否真的有这么多空间
  accessModes:
    - ReadWriteMany                       # 允许多个pod读写,实现共享
  persistentVolumeReclaimPolicy: Recycle  # 回收策略:回收
  nfs:
    path: "/data/pv1"
    server: 10.0.0.11
    readOnly: false
EOF

cat > /k8s_yml/volume/pv2.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
  labels:
    type: nfs001
spec:
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: "/data/pv2"
    server: 10.0.0.11
    readOnly: false
EOF

cat > /k8s_yml/volume/pv3.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv3
  labels:
    type: ssd
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  nfs:
    path: "/data/pv3"
    server: 10.0.0.11
    readOnly: false
EOF

回收策略:

kubectl explain persistentvolumes.spec.persistentVolumeReclaimPolicy
  • Retain(保留):手动回收pv。默认

  • Recycle(回收):基本擦除pv( rm -rf /thevolume/* )

  • Delete(删除):关联的存储资产(例如 AWS EBS、GCE PD、Azure Disk 和 OpenStack Cinder 卷) 将被删除

    当前,只有 NFS 和 HostPath 支持回收策略。AWS EBS、GCE PD、Azure Disk 和 Cinder 卷支持删除策略

  1. master节点创建pv资源
kubectl create namespace tomcat
kubectl create -f .
  1. master节点查看pv资源
kubectl get pv

pv卷状态:

  • Available(可用):一块空闲资源还没有被任何声明绑定
  • Bound(已绑定):卷已经被声明绑定
  • Released(已释放):声明被删除,但是资源还未被集群重新声明
  • Failed(失败):该卷的自动回收失败 命令行会显示绑定到 PV 的 PVC 的名称
  1. master节点创建pvc配置文件
cat > /k8s_yml/volume/mysql_pvc.yaml <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  namespace: tomcat
  name: tomcat-mysql
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 30Gi
EOF
  1. master节点创建pvc资源
kubectl create -f mysql_pvc.yaml
  1. master节点查看pv和pvc资源
kubectl get pv
kubectl get pvc -n tomcat
  1. master节点创建Deployment资源:pod模板里使用volume
cat > /k8s_yml/volume/mysql-rc.yml <<EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: tomcat
  name: mysql
spec:
  replicas: 1
  selector:
    app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      nodeName: 10.0.0.12
      volumes:
      - name: mysql
        persistentVolumeClaim:
          claimName: tomcat-mysql
      containers:
        - name: wp-mysql
          image: 10.0.0.11:5000/mysql:5.7
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 3306
          volumeMounts:
          - mountPath: /var/lib/mysql
            name: mysql
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'
EOF
  1. master节点创建pvc资源
kubectl create -f mysql-rc.yml
  1. master节点验证pv和pvc资源的使用
kubectl get pv 
kubectl get pod -n tomcat
kubectl describe pod -n tomcat mysql-k90jm | grep -i persistentVolumeClaim
kubectl describe pod -n tomcat mysql-k90jm | grep -i tomcat-mysql

回收pv资源

  1. master节点删除tomcat命名空间
kubectl delete namespace tomcat
  1. master节点查看pv处于回收状态,会创建一个pod用来回收(镜像在Google仓库)
kubectl get pv
kubectl get pod
  1. master节点修改镜像地址为阿里云源
kubectl edit pod recycler-for-pv3
    image: registry.aliyuncs.com/google_containers/busybox:latest
  1. master节点查看pod正常运行
kubectl get pod
  1. master节点查看pv回收完毕,处于正常状态
kubectl get pv
kubectl get pv --show-labels

标签选择器(优先)

  1. master节点创建pv配置文件
mkdir /data/pv4 -p
cat > /k8s_yml/volume/pv4.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv4
  labels:
    type: sata
spec:
  capacity:
    storage: 50Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle    #回收策略
  nfs:
    path: "/data/pv4"
    server: 10.0.0.11
    readOnly: false
EOF
  1. master节点创建pv资源
kubectl create -f pv4.yaml
  1. master节点查看pv资源的标签
kubectl get pv --show-labels
  1. master节点创建pvc配置文件:使用标签选择器
cat > /k8s_yml/volume/mysql_pvc2.yaml <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: tomcat-mysql
spec:
  selector:
    matchLabels:
      type: ssd
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
EOF
  1. master节点创建pvc资源
kubectl create -f mysql_pvc2.yaml
  1. master节点验证pv资源优先使用标签选择器的指定
kubectl get pv --show-labels

注:delete也可以,需要安装一定的插件

Ceph

Storage:

  • 存储硬件:nas,san

  • 存储软件:nfs,lvm

Storage方式

  • 块存储:提供硬盘,lvm,cinder
  • 文件存储:提供目录,nfs(单机存储),glusterfs(分布式存储)
  • 对象存储:提供接口,fastdfs,Swift,ceph(分布式存储)
存储方式 技术实现 优势 劣势 代表作
块存储 裸盘上划分逻辑卷,逻辑卷格式化成任意文件系统 支持多种文件系统,传输速度快,提供硬件容错机制 无法实现网络共享 FC-SAN,iSCSI
文件存储 在格式化的磁盘上存储文件 提供网络共享 网络传输速度制约读写速度,分层目录结构限制可扩展性 NFS,FAT,EXT3
对象存储 以灵活可定制的对象为存储单元,元数据服务器提供快速并发寻址 读写速度较快的同时支持网络共享,对象灵活定义 管理软件的购买、使用和运维成本高 Swift

块存储

典型设备: 磁盘阵列,硬盘

块存储主要是将裸磁盘空间整个映射给主机使用的。

通过划逻辑盘、做Raid、或者LVM(逻辑卷)等种种方式逻辑划分出N个逻辑的硬盘。

接着块存储会采用映射的方式将这几个逻辑盘映射给主机,操作系统还需要对挂载的裸硬盘进行分区、格式化后,才能使用,与平常主机内置硬盘的方式完全无异。

优点:

  1. 通过了Raid与LVM等手段,对数据提供了保护。

  2. 将多块廉价的硬盘组合起来,成为一个大容量的逻辑盘对外提供服务,提高了容量。

  3. 可以并行写入,提升读写效率。

  4. 很多时候块存储采用SAN架构组网,传输速率以及封装协议的原因,使得传输速度与读写速率得到提升。

缺点:

  1. 采用SAN架构组网时,需要额外为主机购买光纤通道卡,还要买光纤交换机,成本高。

  2. 主机之间的数据无法共享。不利于不同操作系统主机间的数据共享。


文件存储

典型设备:FTP、NFS服务器

为了克服块存储中文件服务共享的问题,所以有了文件存储。

主机A可以直接对文件存储进行文件的上传下载,与块存储不同,主机A是不需要再对文件存储进行格式化的,因为文件管理功能已经由文件存储自己搞定了。

优点:

  • 造价低:随便一台机器,普通以太网就可以,不需要SAN网络。

  • 方便文件共享:针对块存储中文件无法共享问题,使用文件存储,第三方进行中转。

缺点:

  • 读写速率低,传输速率慢:以太网,上传下载速度较慢;另外所有读写都要1台服务器里面的硬盘来承担,相比起磁盘阵列动不动就几十上百块硬盘同时读写,速率慢了许多。

对象存储

典型设备:内置大容量硬盘的分布式服务器

对象存储最常用的方案,就是多台服务器内置大容量硬盘,再装上对象存储软件,然后搞几台服务器作为管理节点,安装上对象存储管理软件。管理节点可以管理其他服务器对外提供读写访问功能。

块存储读写快,不利于共享,文件存储读写慢,利于共享。能否搞一个读写快,利于共享的出来呢?于是有了对象存储。对象存储结合了块存储与文件存储的优点。

对象存储中,OSD(Object-based Storage Device)是对象存储设备,MDS(Metadata Server)是元数据服务器。

对象存储的原理

首先,一个文件包含了属性(术语叫metadata,元数据,例如该文件的大小、修改时间、存储路径等)以及内容(以下简称数据)。

以往像FAT32这种文件系统,是直接将一份文件的数据与metadata一起存储的,存储过程先将文件按照文件系统的最小块大小来打散(如4M的文件,假设文件系统要求一个块4K,那么就将文件打散成1000个小块),再写进硬盘里面,过程中没有区分数据/metadata的。而每个块最后会告知你下一个要读取的块的地址,然后一直这样顺序地按图索骥,最后完成整份文件的所有块的读取。

对象存储将元数据独立出来,控制节点叫元数据服务器(服务器+对象存储管理软件),里面主要负责存储对象的属性(主要是对象的数据被打散存放到了那几台分布式服务器中的信息),而其他负责存储数据的分布式服务器叫做OSD,主要负责存储文件的数据部分。当用户访问对象,会先访问元数据服务器,元数据服务器只负责反馈对象存储在那些OSD,假设反馈文件A存储在B、C、D三台OSD,那么用户就会再次直接访问3台OSD服务器去读取数据。

这时候由于是3台OSD同时对外传输数据,所以传输的速度就加快了。当OSD服务器数量越多,这种读写速度的提升就越大,通过这种方式,实现了读写快的目的。

另一方面,对象存储软件是有专门的文件系统的,所以OSD对象又相当于文件服务器,那么就不存在文件共享方面的困难了,也就解决了文件共享方面的问题。


总结

  • 块存储可以认为是裸盘,最多包一层逻辑卷(LVM);常见的DAS、FC-SAN、IP-SAN都是块存储,块存储最明显的特征就是不能被操作系统直接读写,需要格式化为指定的文件系统(Ext3、Ext4、NTFS)后才可以访问。优点:读写快(带宽&IOPS);缺点:因为太底层了,不利于扩展。

  • 文件存储:指的是在文件系统上的存储,也就是主机操作系统中的文件系统。

  • 对象存储,对象存储肯定是分布式存储,但分布式存储可能是分布式文件系统,不一定是对象存储;常见的对象存储开源实现有 Ceph 的RADOS、openstack的swift、AWS s3等,常见分布式文件系统,lustre、glusterfs、HDFS等;对象存储和分布式文件系统的表面区别:对象存储支持的访问接口基本都是restful接口、而分布式文件系统提供的POSIX兼容的文件操作接口;

分布式文件系统和对象存储最本质的区别

分布式文件系统文件组织方式为目录树、对象存储采用的则是扁平的组织方式;对象存储不支持随机读取和写入,put和get操作都是针对的整个文件。


Ceph 简介

Ceph 独一无二地在一个统一的系统中同时提供了对象、块、和文件存储功能

它可靠性高、管理简单,并且是开源软件。 Ceph 的强大可以改变您公司的 IT 基础架构和海量数据管理能力。

Ceph 可提供极大的伸缩性——供成千用户访问 PB 乃至 EB 级的数据。 Ceph 节点以普通硬件和智能守护进程作为支撑点, Ceph 存储集群组织起了大量节点,它们之间靠相互通讯来复制数据、并动态地重分布数据。

Ceph 官方文档

Ceph 中文文档

CEPH 对象存储

  • REST 风格的接口
  • 与 S3 和 Swift 兼容的 API
  • S3 风格的子域
  • 统一的 S3/Swift 命名空间
  • 用户管理
  • 利用率跟踪
  • 条带化对象
  • 云解决方案集成
  • 多站点部署
  • 灾难恢复

CEPH 块设备

  • 瘦接口支持
  • 映像尺寸最大 16EB
  • 条带化可定制
  • 内存缓存
  • 快照
  • 写时复制克隆
  • 支持内核级驱动
  • 支持 KVM 和 libvirt
  • 可作为云解决方案的后端
  • 增量备份

CEPH 文件系统

  • 与 POSIX 兼容的语义
  • 元数据独立于数据
  • 动态重均衡
  • 子目录快照
  • 可配置的条带化
  • 有内核驱动支持
  • 有用户空间驱动支持
  • 可作为 NFS/CIFS 部署
  • 可用于 Hadoop (取代 HDFS)

Ceph 特点

高性能

  • 摒弃了传统的集中式存储元数据寻址的方案,采用CRUSH算法,数据分布均衡,并行度高。
  • 考虑了容灾域的隔离,能够实现各类负载的副本放置规则,例如跨机房、机架感知等。
  • 能够支持上千个存储节点的规模,支持TB到PB级的数据。

高可用性

  • 副本数可以灵活控制。
  • 支持故障域分隔,数据强一致性。
  • 多种故障场景自动进行修复自愈。
  • 没有单点故障,自动管理。

高可扩展性

  • 去中心化。
  • 扩展灵活。
  • 随着节点增加而线性增长。

特性丰富

  • 支持三种存储接口:块存储、文件存储、对象存储。
  • 支持自定义接口,支持多种语言驱动。

Ceph 体系结构

stack

stack - 中文

img


Ceph 基础组件

构成 ceph 集群的基础组件:OSD、Manager、MDS、Monitor。

  • OSD(ceph-osd):object storage daemon,对象存储进程。ceph 管理物理硬盘时,引入了OSD概念,每一块盘都会针对的运行一个OSD进程。换句话说,ceph 集群通过管理 OSD 来管理物理硬盘。OSD 一般功能为:存储数据、维护数据副本、数据恢复、数据再平衡以及对ceph monitor组件提供相关监控信息。

  • Manager(ceph-mgr):用于收集ceph集群状态、运行指标,比如存储利用率、当前性能指标和系统负载。对外提供 ceph dashboard(ceph ui)和 resetful api。Manager组件开启高可用时,至少2个。

  • Monitor(ceph-mon):维护集群的状态,包含monitor组件信息,manger 组件信息,osd组件信息,mds组件信息,crush 算法信息。还负责ceph集群的身份验证功能,client在连接ceph集群时通过此组件进行验证。Monitor组件开启高可用时,至少3个。

  • MDS(ceph-mds):Metadata server,元数据服务。为ceph 文件系统提供元数据服务(ceph 对象存储和块存储不需要MDS)。为 posix 文件系统用户提供性能良好的基础命令(ls,find等)。


创建Ceph 存储,至少需要以下服务:

  1. 一个Ceph Monitor
  2. 两个OSD守护进程

Ceph IO算法流程

img

File是用户需要读写的文件。File->Object映射:

  • ino (File的元数据,File的唯一id)。
  • ono(File切分产生的某个object的序号,默认以4M切分一个块大小)。
  • oid(object id: ino + ono)。

Object是RADOS需要的对象。Ceph指定一个静态hash函数计算oid的值,将oid映射成一个近似均匀分布的伪随机值,然后和mask按位相与,得到pgid。Object->PG映射:

  • hash(oid) & mask-> pgid 。
  • mask = PG总数m(m为2的整数幂)-1 。

PG(Placement Group)用于对object的存储进行组织和位置映射, (类似于redis cluster里面的slot的概念) 一个PG里面会有很多object。采用CRUSH算法,将pgid代入其中,然后得到一组OSD。PG->OSD映射:

  • CRUSH(pgid)->(osd1,osd2,osd3) 。

OSD(Object Storage Device)对象存储设备:物理或逻辑存储单元(如LUN)。有时,Ceph用户使用术语“OSD”来指代Ceph OSD守护进程,尽管正确的术语是“Ceph OSD”。


Ceph IO伪代码流程

locator = object_name
obj_hash =  hash(locator)
pg = obj_hash % num_pg
osds_for_pg = crush(pg)  # returns a list of osds
primary = osds_for_pg[0]
replicas = osds_for_pg[1:]

参考文档:


部署Ceph集群

Ceph 集群架构

使用ceph-deploy部署nautilus版Ceph

  • 3个Ceph Monitor
  • 3个Ceph OSD

image-20201210164254751

环境准备

主机名 IP 配置
ceph01 10.0.0.14 1核1G,额外硬盘sdb单个文件50G
ceph02 10.0.0.15 1核1G,额外硬盘sdb单个文件50G
ceph03 10.0.0.16 1核1G,额外硬盘sdb单个文件50G
  • 关闭:selinuxfirewalldNetworkManagerpostfix(非必须)

  • 修改IP地址、主机名

hostnamectl set-hostname 主机名
sed -i 's/200/IP/g' /etc/sysconfig/network-scripts/ifcfg-eth0
  • 添加hosts解析
tee /etc/hosts <<-EOF
10.0.0.14 ceph01
10.0.0.15 ceph02
10.0.0.16 ceph03
EOF
  • 如果热添加硬盘,需要扫描发现硬盘
echo '- - -' >/sys/class/scsi_host/host0/scan
echo '- - -' >/sys/class/scsi_host/host1/scan
echo '- - -' >/sys/class/scsi_host/host2/scan
fdisk -l
  • 准备yum源:Base epel ceph
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
cat > /etc/yum.repos.d/ceph.repo <<EOF
[ceph_x86]
name=ceph_x86
baseurl=https://mirrors.tuna.tsinghua.edu.cn/ceph/rpm-nautilus/el7/x86_64/
gpgcheck=0

[ceph_noarch]
name=ceph_noarch
baseurl=https://mirrors.tuna.tsinghua.edu.cn/ceph/rpm-nautilus/el7/noarch/
gpgcheck=0
EOF

如果你想保留rpm的话,可以开启缓存。

vim /etc/yum.conf
... ...
keepcache=1 # 开启缓存
......

ceph-deploy节点

  1. 配置ssh密钥免密登录所有节点
ssh-keygen
ssh-copy-id root@ceph01
ssh-copy-id root@ceph02
ssh-copy-id root@ceph03

注意: 如果SSH不使用默认22端口时

cat > ~/.ssh/config <<EOF
Port 12345
EOF
  1. 安装ceph-deploy
yum install ceph-deploy -y

所有节点安装

yum install ceph ceph-mon ceph-mgr ceph-radosgw.x86_64 ceph-mds.x86_64   ceph-osd.x86_64 -y
mkdir ceph_rpm
find /var/cache/yum -type f -name "*.rpm" | xargs mv -t ceph_rpm
tar zcf ceph_rpm.tar.gz ceph_rpm
scp ceph_rpm.tar.gz  root@ceph02:/root
scp ceph_rpm.tar.gz  root@ceph03:/root

ceph-deploy使用其内置官网源安装,非常慢!!!因此要提前装好所需包。


ceph-deploy部署ceph集群

  1. ceph01初始化集群配置文件
cd /root
mkdir ceph-deploy && cd ceph-deploy
ceph-deploy new --public-network 10.0.0.0/24 ceph01 ceph02 ceph03

默认[--cluster-network CLUSTER_NETWORK]=[--public-network PUBLIC_NETWORK]

  1. 初始化集群:部署ceph-monitor并启动
ceph-deploy mon create-initial

在各节点生成配置文件/etc/ceph

  1. 创建管理员用户:生成并推送管理员密钥
ceph-deploy admin ceph01 ceph02 ceph03
  1. 查看集群状态:mon存在
ceph -s
  1. 部署ceph-manager并启动
ceph-deploy mgr create ceph01 ceph02 ceph03
  1. 查看集群状态:mon和mgr存在
ceph -s
  1. 创建osd
ceph-deploy osd create ceph01 --data /dev/sdb
ceph-deploy osd create ceph02 --data /dev/sdb
ceph-deploy osd create ceph03 --data /dev/sdb

data:数据盘路径

journal:日志盘路径,日志盘越快,ceph越快。尤其是小块数据I/O,提速明显。

  1. 查看集群状态:mon和mgr和osd存在
ceph -s

如果状态有健康警告如下:

[root@ceph01 ceph-deploy]# ceph -s
cluster:
 id:     a4f16e95-ba09-49f5-b0bf-ada31833a457
 health: HEALTH_WARN
         clock skew detected on mon.ceph03

services:
 mon: 3 daemons, quorum ceph01,ceph02,ceph03 (age 23m)
 mgr: ceph01(active, since 53m), standbys: ceph02, ceph03
 osd: 3 osds: 3 up (since 29m), 3 in (since 29m)

data:
 pools:   0 pools, 0 pgs
 objects: 0 objects, 0 B
 usage:   3.0 GiB used, 147 GiB / 150 GiB avail
 pgs:

生产环境请使用ntp服务


测试环境可以调整ceph配置中的[global]下时间偏差阈值:

cat >> /root/ceph-deploy/ceph.conf <<EOF
mon clock drift allowed = 2
mon clock drift warn backoff = 30
EOF

向所有同步的mon节点推送配置文件,重启mon服务:

ceph-deploy --overwrite-conf config push ceph0{1,2,3}
systemctl restart ceph-mon.target

最后查看集群状态:HEALTH_OK

  1. 查看monitors信息
ceph mon dump

ceph 资源配置

  1. 创建pool资源池
ceph osd pool create k8s 128 128
  1. 查看pool资源池
ceph osd pool ls
ceph osd pool stats k8s
  1. 调整pool资源池的ps数量
ceph osd pool set k8s pg_num 128
  1. 创建RBD块设备
rbd create --size 1024 k8s/tomcat_mysql.img
  1. 查看RBD块设备
rbd info k8s/tomcat_mysql.img
rbd info --pool k8s tomcat_mysql.img
rbd info --pool k8s --image tomcat_mysql.img
  1. 查看OSD节点数量
ceph osd pool get k8s size

增加OSD节点会自动进行数据整合,请在业务低谷期间增加,一台一台慢慢加。

  1. 查看RBD块设备所有对象
rados -p k8s ls
rados -p k8s ls | grep rbd_data.ac74b202ed1a
rados -p k8s ls | grep rbd_data.ac74b202ed1a | wc -l

用多少,分多少。

  1. 树状显示所有OSD
ceph osd tree

使用RBD块设备

  1. 禁用高级特性
rbd feature disable k8s/tomcat_mysql.img object-map fast-diff deep-flatten
  1. 映射到实际设备
rbd map k8s/tomcat_mysql.img
/dev/rbd0

关机映射失效,需要重新映射,数据不会丢失。

  1. 格式化
mkfs.xfs /dev/rbd0
  1. 挂载
mount /dev/rbd0 /mnt
  1. 卸载
umount /mnt
  1. 扩容
rbd resize --size 2048 k8s/tomcat_mysql.img
  1. 挂载
mount /dev/rbd0 /mnt
  1. 调整容量
xfs_growfs /dev/rbd0
  1. 挂载,查看
df -Th

Ceph 对接 k8s

Ceph RBD 对接 k8s :参考官方文档


准备

所有k8s node节点安装ceph-common

cat > /etc/yum.repos.d/ceph.repo <<EOF
[ceph_x86]
name=ceph_x86
baseurl=https://mirrors.tuna.tsinghua.edu.cn/ceph/rpm-nautilus/el7/x86_64/
gpgcheck=0

[ceph_noarch]
name=ceph_noarch
baseurl=https://mirrors.tuna.tsinghua.edu.cn/ceph/rpm-nautilus/el7/noarch/
gpgcheck=0
EOF
yum -y install ceph-common

ceph01

  1. 推送ceph用户密钥文件和配置文件给所有k8s node节点
scp -rp /etc/ceph/ceph.client.admin.keyring root@10.0.0.12:/etc/ceph/
scp -rp /etc/ceph/ceph.client.admin.keyring root@10.0.0.13:/etc/ceph/
scp -rp /etc/ceph/ceph.conf root@10.0.0.12:/etc/ceph/
scp -rp /etc/ceph/ceph.conf root@10.0.0.13:/etc/ceph/
  1. 获取base64加密的ceph用户key
grep key /etc/ceph/ceph.client.admin.keyring |awk '{printf "%s", $NF}'|base64
  1. 创建最小特性镜像
rbd create --size 2048 --image-feature layering k8s/test.img
rbd ls -p k8s

k8s-master

  1. master节点编写Secret资源yaml
mkdir -p /k8s_yml/ceph && cd /k8s_yml/ceph
cat > /k8s_yml/ceph/ceph-secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
  namespace: tomcat
  name: ceph-secret
type: "kubernetes.io/rbd"
data:
  key: QVFCQzNkUmZsL0tPQWhBQUV5L1g5a2NHb0NTTkJKclZVS0xXekE9PQ==
EOF
  1. master节点创建Secret资源
kubectl create namespace tomcat
kubectl create -f ceph-secret.yaml
  1. master节点查看Secret资源
kubectl get secret -n tomcat
  1. master节点查看Secret资源配置文件
kubectl get secret -n tomcat ceph-secret -o yaml

能看到ceph用户key,可以解密。


pod 对接ceph rbs存储

查看计划信息

kubectl explain pod.spec.volumes.rbd
  1. master节点编写Pod资源yaml
cat > /k8s_yml/ceph/test_ceph_pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  namespace: tomcat
  name: rbd
spec:
  containers:
    - image: 10.0.0.11:5000/nginx:1.13
      name: rbd-rw
      volumeMounts:
      - name: rbdpd
        mountPath: /data
  volumes:
    - name: rbdpd
      rbd: 
        monitors:
        - '10.0.0.14:6789'
        - '10.0.0.15:6789'
        - '10.0.0.16:6789'
        pool: k8s
        image: test.img
        fsType: ext4
        user: admin
        keyring: /etc/ceph/keyring
        secretRef:
          name: ceph-secret
EOF
  1. master节点创建Pod资源
kubectl create -f test_ceph_pod.yaml
  1. master节点查看Pod资源
kubectl get pod -o wide -n tomcat
  1. master节点进入容器,查看有/dev/rbd0设备,验证对接成功
kubectl exec -n tomcat -it rbd /bin/bash
df -h
  1. node节点查看所有映射的rbd
rbd device ls

pv 对接ceph rbs存储

  1. master节点编写PV资源yaml
cat > /k8s_yml/ceph/ceph_pv1.yaml <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: ceph01
  labels:
    type: rbd
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  rbd:
    monitors:
    - '10.0.0.14:6789'
    - '10.0.0.15:6789'
    - '10.0.0.16:6789'
    pool: k8s
    image: test2.img
    fsType: xfs
    user: admin
    secretRef:
      name: ceph-secret
EOF

注意:请使用xfs格式。

ext4格式默认创建一个lost+found目录,导致mysql无法启动。

  • 需要手动删除

    df -Th|grep rbd
    rm -fr /var/lib/kubelet/plugins/kubernetes.io/rbd/rbd/k8s-image-test2.img/*
    
  • 或者使用initContainer配置项,参考文档

  1. ceph创建最小特性镜像
rbd create --size 2048 --image-feature layering k8s/test.img
rbd ls -p k8s
  1. master节点创建pv资源
kubectl create -f ceph_pv1.yaml
  1. master节点查看pv资源
kubectl get pv -o wide
  1. master节点编写PVC资源yaml
cat > /k8s_yml/ceph/ceph_pvc.yaml <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: tomcat-rbd1
  namespace: tomcat
spec:
  selector:
    matchLabels:
      type: rbd
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
EOF
  1. master节点创建pvc资源
kubectl create -f ceph_pvc.yaml
  1. master节点查看pvc资源
kubectl get pvc -n tomcat -o wide
  1. master节点编写Deployment资源yaml
cat > /k8s_yml/ceph/mysql-deploy.yaml <<EOF        
apiVersion: extensions/v1beta1         
kind: Deployment
metadata:
  namespace: tomcat        
  name: mysql
spec:
  replicas: 1           
  template:            
    metadata:
      labels:
        app: mysql 
    spec:
      volumes:
      - name: mysql
        persistentVolumeClaim:
          claimName: tomcat-rbd1
      containers:
        - name: wp-mysql
          image: 10.0.0.11:5000/mysql:5.7
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 3306
          volumeMounts:
          - mountPath: /var/lib/mysql
            name: mysql
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: '123456'
EOF
  1. master节点创建Deployment资源
kubectl create -f mysql-deploy.yaml
  1. master节点查看Deployment资源
kubectl get pod -n tomcat -o wide

Jenkins实现k8s持续更新

环境准备

主机名 IP 服务 内存
k8s-master 10.0.0.11 kube-apiserver 8080 1G
k8s-node-1 10.0.0.12 kube-apiserver 8080 1G
k8s-node-2 10.0.0.13 Jenkins(tomcat + jdk) 8080 2G
  • 代码仓库使用gitee托管

image-20201211160845138


gitee仓库准备

  1. 创建远程仓库

image-20201213214550908

  1. Git 全局设置:
git config --global user.name "刘朋辉"
git config --global user.email "15094034633@163.com"
  • 新仓库:
mkdir oldboy
cd oldboy
git init
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin https://gitee.com/stronger-DAWEI/oldboy.git
git push -u origin master
  • 已有仓库:
cd /opt
git remote remove origin
git remote add origin https://gitee.com/stronger-DAWEI/oldboy.git
git push -u origin master

jenkins部署(k8s-node-2)

  1. 准备Jenkins + tomcat + jdk
cd /opt
for n in apache-tomcat-8.0.27.tar.gz jdk-8u102-linux-x64.rpm jenkin-data.tar.gz jenkins.war;do wget http://192.168.15.253/k8s_jenkins/$n ;done
  1. 二进制安装jenkins
rpm -ivh jdk-8u102-linux-x64.rpm 
mkdir /app -p
tar xf apache-tomcat-8.0.27.tar.gz -C /app
rm -fr /app/apache-tomcat-8.0.27/webapps/*
mv jenkins.war /app/apache-tomcat-8.0.27/webapps/ROOT.war
tar xf jenkin-data.tar.gz -C /root
/app/apache-tomcat-8.0.27/bin/startup.sh 
netstat -lntup

jenkins构建测试

  1. 访问jenkins:http://10.0.0.13:8080/,默认账号密码 admin:123456
  2. 创建一个新任务

image-20201211120409267

  1. 配置jenkins拉取gitlab代码凭据

image-20201211120743488

image-20201211120622384

  1. 构建Shell测试

image-20201211121051759

  1. 立即构建

image-20201211121150223

  1. 查看控制台输出

image-20201214222357074


构建docker镜像node01

  1. docker镜像底包:nginx:1.13 nginx nginx+php tomcat

  2. 编写dockerfile.dockerignore并运行测试

cat > dockerfile <<EOF
FROM 10.0.0.11:5000/nginx:1.13
RUN rm -rf /usr/share/nginx/html/*
ADD . /usr/share/nginx/html
EOF
echo dockerfile > .dockerignore
docker build -t test:v1 .
docker run -d -p 80:80 test:v1
  1. 浏览器访问http://10.0.0.12/

  2. 上传dockerfile.dockerignore到私有仓库

git add .dockerignore dockerfile
git commit -m "add dockerfile"
git push -u origin master
  1. gitee添加标签v1,修改首页,添加标签v2

    image-20201214225942511

  2. master节点手动发布

kubectl create namespace oldboy
kubectl run -n oldboy oldboy --image=10.0.0.11:5000/oldboy:v1 --replicas=2
kubectl expose -n oldboy deploy oldboy --type=NodePort --port=80 --target-port=80
kubectl get all -n oldboy
kubectl  set image -n oldboy deploy oldboy oldboy=10.0.0.11:5000/oldboy:v2

jenkins滚动更新

  1. 使用参数构建

image-20201211150942890

  1. 修改Shell
docker build -t 10.0.0.11:5000/oldboy:$version .
docker push 10.0.0.11:5000/oldboy:$version
kubectl -s 10.0.0.11:8080 set image -n oldboy deploy oldboy oldboy=10.0.0.11:5000/oldboy:$version

image-20201211152147688

  1. 执行测试

Build with Parameters --> 输入版本 --> 开始构建

jenkins从gitee下载代码,构建docker镜像并上传到私有仓库,调用k8s滚动发布。

  1. 查看控制台输出

image-20201211151931346

  1. shell脚本
if [ -f /tmp/oldboy.lock ];then
    docker build -t 10.0.0.11:5000/oldboy:v$version .
    docker push 10.0.0.11:5000/oldboy:v$version
    kubectl -s 10.0.0.11:8080 set image -n oldboy deploy oldboy oldboy=10.0.0.11:5000/oldboy:v$version
    port=`kubectl -s 10.0.0.11:8080  get svc -n oldboy|grep -oP '(?<=80:)\d+'`
    echo "你的项目地址访问是http://10.0.0.13:$port"
    echo "更新成功"
else
    docker build -t 10.0.0.11:5000/oldboy:v$version  .
    docker push 10.0.0.11:5000/oldboy:v$version
    kubectl -s 10.0.0.11:8080 create namespace oldboy
    kubectl -s 10.0.0.11:8080 run oldboy -n oldboy  --image=10.0.0.11:5000/oldboy:v$version --replicas=3 --record
    kubectl -s 10.0.0.11:8080 expose -n oldboy deployment oldboy --port=80 --type=NodePort
    port=`kubectl -s 10.0.0.11:8080  get svc -n oldboy|grep -oP '(?<=80:)\d+'`
    echo "你的项目地址访问是http://10.0.0.13:$port"
    echo "发布成功"
    touch /tmp/oldboy.lock
    chattr +i /tmp/oldboy.lock
fi

jenkins一键回滚

另建一个工程,不需要拉代码,仅仅需要指定版本参数和shell,参数化回滚:

kubectl -s 10.0.0.11:8080 set image -n oldboy deploy oldboy oldboy=10.0.0.11:5000/oldboy:$version

k8s高可用

架构

image-20201211174520119

主机名 IP 服务
k8s-master01 10.0.0.11 api-server,controller-manager,scheduler,etcd,keepalived,flannel
k8s-master02 10.0.0.12 api-server,controller-manager,scheduler,etcd,keepalived,flannel
k8s-node-1 10.0.0.13 kubernetes-node,flannel

etcd高可用集群

不能单机扩集群,首次使用请使用集群,集群是奇数个,竞选。(虚拟机请还原快照)

  1. 所有节点安装
yum install etcd -y
  1. 所有节点配置
#[Member]
#ETCD_CORS=""
ETCD_DATA_DIR="/var/lib/etcd/"
#ETCD_WAL_DIR=""
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
#ETCD_MAX_SNAPSHOTS="5"
#ETCD_MAX_WALS="5"
ETCD_NAME="node1"  # 节点的名字
#ETCD_SNAPSHOT_COUNT="100000"
#ETCD_HEARTBEAT_INTERVAL="100"
#ETCD_ELECTION_TIMEOUT="1000"
#ETCD_QUOTA_BACKEND_BYTES="0"
#ETCD_MAX_REQUEST_BYTES="1572864"
#ETCD_GRPC_KEEPALIVE_MIN_TIME="5s"
#ETCD_GRPC_KEEPALIVE_INTERVAL="2h0m0s"
#ETCD_GRPC_KEEPALIVE_TIMEOUT="20s"
#
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.11:2380" # 节点同步数据的地址
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.11:2379"       # 节点提供服务的地址
#ETCD_DISCOVERY=""
#ETCD_DISCOVERY_FALLBACK="proxy"
#ETCD_DISCOVERY_PROXY=""
#ETCD_DISCOVERY_SRV=""
ETCD_INITIAL_CLUSTER="node1=http://10.0.0.11:2380,node2=http://10.0.0.12:2380,node3=http://10.0.0.13:2380"               # 初始化集群
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"  # 初始化集群令牌
ETCD_INITIAL_CLUSTER_STATE="new"           # 初始化集群状态
cat > /etc/etcd/etcd.conf <<EOF
#[Member]
#ETCD_CORS=""
ETCD_DATA_DIR="/var/lib/etcd/"
#ETCD_WAL_DIR=""
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
#ETCD_MAX_SNAPSHOTS="5"
#ETCD_MAX_WALS="5"
ETCD_NAME="node1"
#ETCD_SNAPSHOT_COUNT="100000"
#ETCD_HEARTBEAT_INTERVAL="100"
#ETCD_ELECTION_TIMEOUT="1000"
#ETCD_QUOTA_BACKEND_BYTES="0"
#ETCD_MAX_REQUEST_BYTES="1572864"
#ETCD_GRPC_KEEPALIVE_MIN_TIME="5s"
#ETCD_GRPC_KEEPALIVE_INTERVAL="2h0m0s"
#ETCD_GRPC_KEEPALIVE_TIMEOUT="20s"
#
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.11:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.11:2379"
#ETCD_DISCOVERY=""
#ETCD_DISCOVERY_FALLBACK="proxy"
#ETCD_DISCOVERY_PROXY=""
#ETCD_DISCOVERY_SRV=""
ETCD_INITIAL_CLUSTER="node1=http://10.0.0.11:2380,node2=http://10.0.0.12:2380,node3=http://10.0.0.13:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
#ETCD_STRICT_RECONFIG_CHECK="true"
#ETCD_ENABLE_V2="true"
#
#[Proxy]
#ETCD_PROXY="off"
#ETCD_PROXY_FAILURE_WAIT="5000"
#ETCD_PROXY_REFRESH_INTERVAL="30000"
#ETCD_PROXY_DIAL_TIMEOUT="1000"
#ETCD_PROXY_WRITE_TIMEOUT="5000"
#ETCD_PROXY_READ_TIMEOUT="0"
#
#[Security]
#ETCD_CERT_FILE=""
#ETCD_KEY_FILE=""
#ETCD_CLIENT_CERT_AUTH="false"
#ETCD_TRUSTED_CA_FILE=""
#ETCD_AUTO_TLS="false"
#ETCD_PEER_CERT_FILE=""
#ETCD_PEER_KEY_FILE=""
#ETCD_PEER_CLIENT_CERT_AUTH="false"
#ETCD_PEER_TRUSTED_CA_FILE=""
#ETCD_PEER_AUTO_TLS="false"
#
#[Logging]
#ETCD_DEBUG="false"
#ETCD_LOG_PACKAGE_LEVELS=""
#ETCD_LOG_OUTPUT="default"
#
#[Unsafe]
#ETCD_FORCE_NEW_CLUSTER="false"
#
#[Version]
#ETCD_VERSION="false"
#ETCD_AUTO_COMPACTION_RETENTION="0"
#
#[Profiling]
#ETCD_ENABLE_PPROF="false"
#ETCD_METRICS="basic"
#
#[Auth]
#ETCD_AUTH_TOKEN="simple"
EOF
# node2
cat > /etc/etcd/etcd.conf <<EOF
#[Member]
#ETCD_CORS=""
ETCD_DATA_DIR="/var/lib/etcd/"
#ETCD_WAL_DIR=""
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
#ETCD_MAX_SNAPSHOTS="5"
#ETCD_MAX_WALS="5"
ETCD_NAME="node2"
#ETCD_SNAPSHOT_COUNT="100000"
#ETCD_HEARTBEAT_INTERVAL="100"
#ETCD_ELECTION_TIMEOUT="1000"
#ETCD_QUOTA_BACKEND_BYTES="0"
#ETCD_MAX_REQUEST_BYTES="1572864"
#ETCD_GRPC_KEEPALIVE_MIN_TIME="5s"
#ETCD_GRPC_KEEPALIVE_INTERVAL="2h0m0s"
#ETCD_GRPC_KEEPALIVE_TIMEOUT="20s"
#
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.12:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.12:2379"
#ETCD_DISCOVERY=""
#ETCD_DISCOVERY_FALLBACK="proxy"
#ETCD_DISCOVERY_PROXY=""
#ETCD_DISCOVERY_SRV=""
ETCD_INITIAL_CLUSTER="node1=http://10.0.0.11:2380,node2=http://10.0.0.12:2380,node3=http://10.0.0.13:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
#ETCD_STRICT_RECONFIG_CHECK="true"
#ETCD_ENABLE_V2="true"
#
#[Proxy]
#ETCD_PROXY="off"
#ETCD_PROXY_FAILURE_WAIT="5000"
#ETCD_PROXY_REFRESH_INTERVAL="30000"
#ETCD_PROXY_DIAL_TIMEOUT="1000"
#ETCD_PROXY_WRITE_TIMEOUT="5000"
#ETCD_PROXY_READ_TIMEOUT="0"
#
#[Security]
#ETCD_CERT_FILE=""
#ETCD_KEY_FILE=""
#ETCD_CLIENT_CERT_AUTH="false"
#ETCD_TRUSTED_CA_FILE=""
#ETCD_AUTO_TLS="false"
#ETCD_PEER_CERT_FILE=""
#ETCD_PEER_KEY_FILE=""
#ETCD_PEER_CLIENT_CERT_AUTH="false"
#ETCD_PEER_TRUSTED_CA_FILE=""
#ETCD_PEER_AUTO_TLS="false"
#
#[Logging]
#ETCD_DEBUG="false"
#ETCD_LOG_PACKAGE_LEVELS=""
#ETCD_LOG_OUTPUT="default"
#
#[Unsafe]
#ETCD_FORCE_NEW_CLUSTER="false"
#
#[Version]
#ETCD_VERSION="false"
#ETCD_AUTO_COMPACTION_RETENTION="0"
#
#[Profiling]
#ETCD_ENABLE_PPROF="false"
#ETCD_METRICS="basic"
#
#[Auth]
#ETCD_AUTH_TOKEN="simple"
EOF
# node3
cat > /etc/etcd/etcd.conf <<EOF
#[Member]
#ETCD_CORS=""
ETCD_DATA_DIR="/var/lib/etcd/"
#ETCD_WAL_DIR=""
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
#ETCD_MAX_SNAPSHOTS="5"
#ETCD_MAX_WALS="5"
ETCD_NAME="node3"
#ETCD_SNAPSHOT_COUNT="100000"
#ETCD_HEARTBEAT_INTERVAL="100"
#ETCD_ELECTION_TIMEOUT="1000"
#ETCD_QUOTA_BACKEND_BYTES="0"
#ETCD_MAX_REQUEST_BYTES="1572864"
#ETCD_GRPC_KEEPALIVE_MIN_TIME="5s"
#ETCD_GRPC_KEEPALIVE_INTERVAL="2h0m0s"
#ETCD_GRPC_KEEPALIVE_TIMEOUT="20s"
#
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.0.0.13:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.13:2379"
#ETCD_DISCOVERY=""
#ETCD_DISCOVERY_FALLBACK="proxy"
#ETCD_DISCOVERY_PROXY=""
#ETCD_DISCOVERY_SRV=""
ETCD_INITIAL_CLUSTER="node1=http://10.0.0.11:2380,node2=http://10.0.0.12:2380,node3=http://10.0.0.13:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
#ETCD_STRICT_RECONFIG_CHECK="true"
#ETCD_ENABLE_V2="true"
#
#[Proxy]
#ETCD_PROXY="off"
#ETCD_PROXY_FAILURE_WAIT="5000"
#ETCD_PROXY_REFRESH_INTERVAL="30000"
#ETCD_PROXY_DIAL_TIMEOUT="1000"
#ETCD_PROXY_WRITE_TIMEOUT="5000"
#ETCD_PROXY_READ_TIMEOUT="0"
#
#[Security]
#ETCD_CERT_FILE=""
#ETCD_KEY_FILE=""
#ETCD_CLIENT_CERT_AUTH="false"
#ETCD_TRUSTED_CA_FILE=""
#ETCD_AUTO_TLS="false"
#ETCD_PEER_CERT_FILE=""
#ETCD_PEER_KEY_FILE=""
#ETCD_PEER_CLIENT_CERT_AUTH="false"
#ETCD_PEER_TRUSTED_CA_FILE=""
#ETCD_PEER_AUTO_TLS="false"
#
#[Logging]
#ETCD_DEBUG="false"
#ETCD_LOG_PACKAGE_LEVELS=""
#ETCD_LOG_OUTPUT="default"
#
#[Unsafe]
#ETCD_FORCE_NEW_CLUSTER="false"
#
#[Version]
#ETCD_VERSION="false"
#ETCD_AUTO_COMPACTION_RETENTION="0"
#
#[Profiling]
#ETCD_ENABLE_PPROF="false"
#ETCD_METRICS="basic"
#
#[Auth]
#ETCD_AUTH_TOKEN="simple"
EOF
  1. 所有节点同时启动,并加入开机自启
systemctl enable etcd
systemctl start etcd
  1. 检查集群健康状态和成员列表
etcdctl cluster-health
etcdctl member list

flannel配置

  1. 修改配置文件
sed -i "4c FLANNEL_ETCD_ENDPOINTS="http://10.0.0.11:2379,http://10.0.0.12:2379,http://10.0.0.13:2379"" /etc/sysconfig/flanneld
  1. 创建key
etcdctl mk /atomic.io/network/config '{ "Network": "172.18.0.0/16","Backend": {"Type": "vxlan"} }'
  1. 启动并加入开机自启
systemctl start flanneld
systemctl enable flanneld
systemctl restart docker
  1. 检查网卡
ip a

master节点

master01和master02部署api-server,controller-manager,scheduler

  1. 安装
yum install kubernetes-master -y
  1. 配置apiserver
sed -i "8c KUBE_API_ADDRESS=\"--insecure-bind-address=0.0.0.0\"" /etc/kubernetes/apiserver
sed -i "11c KUBE_API_PORT=\"--port=8080\"" /etc/kubernetes/apiserver
sed -i "14c KUBELET_PORT=\"--kubelet-port=10250\"" /etc/kubernetes/apiserver
sed -i "17c KUBE_ETCD_SERVERS=\"--etcd-servers=http://10.0.0.11:2379,http://10.0.0.12:2379,http://10.0.0.13:2379\"" /etc/kubernetes/apiserver
sed -i "s/ServiceAccount,//" /etc/kubernetes/apiserver
  1. 配置config
sed -i "22c KUBE_MASTER=\"--master=http://127.0.0.1:8080\"" /etc/kubernetes/config
  1. 启动并加入开机启动
systemctl enable kube-apiserver.service
systemctl enable kube-controller-manager.service
systemctl enable kube-scheduler.service
systemctl restart kube-apiserver.service
systemctl restart kube-controller-manager.service
systemctl restart kube-scheduler.service
  1. 检查服务是否安装正常
kubectl get componentstatus

Keepalived配置

在master01和master02安装keepalived。

  1. 安装
yum install keepalived -y
  1. master01配置
cat > /etc/keepalived/keepalived.conf <<EOF
! Configuration File for keepalived

global_defs {
   router_id LVS_DEVEL_11
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.10
    }
}
EOF
  1. master02配置
cat > /etc/keepalived/keepalived.conf <<EOF
! Configuration File for keepalived

global_defs {
   router_id LVS_DEVEL_12
}

vrrp_instance VI_1 {
    state BACKUP
    interface eth0
    virtual_router_id 51
    priority 80
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.10
    }
}
EOF
  1. 启动并加入开机自启
systemctl enable keepalived
systemctl start keepalived

node节点

所有node节点的kubelet,kube-proxy指向api-server的vip。

  1. 安装:见k8s集群yum安装
  2. 配置
sed -i "22c KUBE_MASTER=\"--master=http://10.0.0.10:8080\"" /etc/kubernetes/config
sed -i "14c KUBELET_API_SERVER=\"--api-servers=http://10.0.0.10:8080\"" /etc/kubernetes/kubelet
  1. 重启生效
systemctl restart kubelet.service kube-proxy.service
kubectl get nodes

任意关掉一台进行测试

posted @ 2021-03-06 15:07  上善若水~小辉  阅读(550)  评论(0编辑  收藏  举报