目 录
一、 第一部分:云计算 IV
- 什么是云计算? IV
- 云计算的服务类型 V
- 为什么要用云计算 V
- 云计算的基础KVM虚拟化 VI
- kvm管理平台 XVII
二、 第二部分 docker容器 XIX - 什么是容器 XIX
- 容器和虚拟机的区别 XIX
- docker-ce的安装 XX
- docker主要内容 XX
- docker镜像常用命令 XXI
- docker容器的常用命令 XXII
- docker端口映射 XXV
- docker数据卷 XXV
- 手动制作docker镜像 XXVI
- 自动制作docker镜像 XXIX
- docker镜像的分层(复用,节省空间) XXXII
- dockerfile的优化 XXXII
- 容器间的互联 XXXIII
- 单机版的容器编排 XXXIV
- 私有仓库docker-registry XXXVI
- 企业级私有仓库harbor(docker-compose) XXXVII
- docker基础网络 XLI
- 跨宿主机容器间的通讯之macvlan XLII
- 跨宿主机容器间的通讯之overlay XLIII
- docker容器的监控 XLIII
三、 第三部分:k8s LVI - k8s集群的安装 LVI
- 什么是k8s,k8s有什么功能? 5
- k8s常用的资源 9
- k8s的常用资源(二进制) 23
- k8s常用服务(二进制) 34
- k8s的网络访问(二进制) 48
- K8s的附加组件 63
- k8s弹性伸缩 70
8.1 使用heapster实现弹性伸缩 70 - 使用kubeadm初始化k8s集群 73
9.1 环境要求: 74
9.2 安装指定版本docker 74
9.3 安装kubeadm 74
9.4 使用kubeadm初始化k8s集群 75
9.5 给k8s集群加入node节点: 75
9.6 为k8s集群配置网络插件 75
9.7 为k8s集群配置dashboard服务 76
9.8 使用metric-server实现弹性伸缩 77 - 持久化存储 85
10.1 emptyDir: 85
10.2 HostPath:[不能跨宿主机做数据共享] 85
10.3 Nfs(网络文件共享) 86
10.4 pv和pvc: 86
10.5 分布式存储ceph 88 - 使用jenkins实现k8s持续更新 95
11.1 安装gitlab并上传代码 96
11.2 安装jenkins,并自动构建docker镜像 97 - k8s高可用 101
- 基于nfs实现动态存储(二进制) 104
- Helm k8s包管理工具 107
14.1 helm介绍: [部署应用变得更简单、高效] 107
14.2 helm安装 107
14.3 helm初始化 108
14.4 自定义helm 110 - statsfulset资源 116
- job资源和cron.job资源 117
- kubesphere管理平台 118
- 阿里云k8s 120
四、 第四部分:阿里云 122 - 云计算回顾 122
- 阿里云的发展历程: 123
- 阿里云的控制台 123
- ECS资源(弹性计算)-快照-镜像-云硬盘 123
一、 第一部分:云计算
-
什么是云计算?
云计算是一种按量付费的模式!云计算的底层是通过虚拟化技术来实现的! -
云计算的服务类型
IAAS 基础设施即服务(infrastructure as an service) 虚拟机 ecs云主机
PAAS 平台即服务(platform as an service ) PHP,java 容器
SAAS 软件即服务(software as an service ) 企业邮箱服务 cdn服务 rds数据库 -
为什么要用云计算
小公司:10台 20w+ idc 5w + 100M 10W, 10台云主机,前期投入小,扩展灵活,风险小
大公司:闲置服务器计算资源,虚拟机,出租(超卖)
64G 服务器 64台1G 320台1G 64台 大公司自己的业务 264台 租出去
国企,银行
公有云: 谁都可以租
私有云: 只有公司内部使用
混合云: 有自己的私有云 + 租的公有云 -
云计算的基础KVM虚拟化
宿主机:内存4G+ 纯净的系统CentOS-7(关闭selinux,firewalld和NetworkManager)
4.1 什么是虚拟化?
虚拟化,通过模拟计算机的硬件,来实现在同一台计算机上同时运行多个不同的操作系统的技术。
4.2 linux虚拟化软件的差别
linux虚拟化软件: qemu 软件纯模拟全虚拟化软件,特别慢!兼容性好! xen(半) 性能特别好,需要使用专门修改之后的内核,兼容性差! redhat 5.5 xen kvm KVM(linux) 全虚拟机,它有硬件支持cpu,内置在linux内核模块,而且不需要使用专门的内核 centos6 kvm 性能较好,兼容较好
vmware workstations: 图形界面
virtual Box: 图形界面 Oracle
4.3 安装kvm虚拟化管理工具
主机名 ip地址 内存 虚拟机
kvm01 10.0.0.11 4G(后期调整到2G) cpu开启vt虚拟化
kvm02 10.0.0.12 2G cpu开启vt虚拟化
yum install libvirt virt-install qemu-kvm -y
KVM:Kernel-based Virtual Machine
libvirt 作用:虚拟机的管理软件 libvirt: kvm,xen,qemu,lxc…
virt virt-install virt-clone 作用:虚拟机的安装工具和克隆工具 qemu-kvm qemu-img (qcow2,raw)作用:管理虚拟机的虚拟磁盘
环境要求:
centos 7.4 7.6 7.8(不要使用7.5)
vmware 宿主机 kvm虚拟机
内存4G,cpu开启虚拟化
IP:10.0.0.11
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
安装软件包
yum install libvirt virt-install qemu-kvm -y
4.4 安装一台kvm虚拟机
VNC-Viewer-6.19.325
微软的远程桌面
vnc:远程的桌面管理工具 向日葵 微软的远程桌面
systemctl start libvirtd.service systemctl status libvirtd.service
10.0.0.11 宿主机
建议虚拟机内存不要低于1024M,否则安装系统特别慢!
virt-install --virt-type kvm --os-type=linux --os-variant rhel7 --name centos7 --memory 1024 --vcpus 1 --disk /opt/centos2.raw,format=raw,size=10 --cdrom /opt/CentOS-7-x86_64-DVD-1708.iso --network network=default --graphics vnc,listen=0.0.0.0 --noautoconsole
vnc:10.0.0.11:5900
–virt-type kvm 虚拟化的类型(qemu) --os-type=linux 系统类型 --os-variant rhel7 系统版本 --name centos7 虚拟机的名字 (必须唯一) --memory 1024 虚拟机的内存 --vcpus 1 虚拟cpu的核数 --disk /opt/centos2.raw,format=raw,size=10(必须唯一) --cdrom /opt/CentOS-7-x86_64-DVD-1708.iso --network network=default 使用默认NAT的网络 --graphics vnc,listen=0.0.0.0 --noautoconsole (可有可无)
云主机都没有swap分区
4.5 kvm虚拟机的virsh日常管理和配置
列表list(–all) 开机start 关机shutdown(虚拟机有系统) 拔电源关机destroy 重启reboot(虚拟机有系统)
导出配置dumpxml 例子:virsh dumpxml centos7 >centos7-off.xml 删除undefine 推荐:先destroy,在undefine 导入配置define 修改配置edit(自带语法检查) 重命名domrename (低版本不支持)
挂起suspend 恢复resume 查询vnc端口号vncdisplay
kvm虚拟机开机启动 kvm运行业务程序 开机启动autostart,前提:systemctl enable libvirtd; 取消开机启动autostart --disable
console 控制台 登录
centos7的kvm虚拟机:
grubby --update-kernel=ALL --args=“console=ttyS0,115200n8”
reboot
作业1:安装一台centos6的kvm虚拟机,实现console登录 安装一台centos6的kvm虚拟机,在安装的过程中.内核参数selinux=0
4.6 kvm虚拟机虚拟磁盘管理和快照管理
raw: 俗称裸格式,占用空间比较大,不支持快照功能,不方便传输 ,读写性能较好 总50G,用1G,传输50G qcow2: qcow(copy on write)占用空间小,支持快照,性能比raw差一点,方便传输 总50G,用1G,传输1G
virt-install --virt-type kvm --os-type=linux --os-variant rhel7 --name centos7 --memory 1024 --vcpus 1 --disk /opt/centos2.raw,format=raw,size=10 --cdrom /opt/CentOS-7-x86_64-DVD-1708.iso --network network=default --graphics vnc,listen=0.0.0.0 --noautoconsole
virt-install --virt-type kvm --os-type=linux --os-variant rhel7 --name centos7 --memory 1024 --vcpus 1 --disk /opt/oldboy.qcow2,format=qcow2,size=10 --cdrom /data/CentOS-7.2-x86_64-DVD-1511.iso --network network=default --graphics vnc,listen=0.0.0.0 --noautoconsole
4.6.1 磁盘工具的常用命令
qemu-img info,create,resize,convert
查看虚拟磁盘信息 qemu-img info test.qcow2
创建一块qcow2格式的虚拟硬盘: qemu-img create -f qcow2 test.qcow2 2G
调整磁盘磁盘容量 qemu-img resize test.qcow2 +20G
raw转qcow2:qemu-img convert -f raw -O qcow2 oldboy.raw oldboy.qcow2 -c 压缩 virsh edit web01:
virsh destroy web01 virsh start web01
4.6.2 快照管理
创建快照virsh snapshot-create-as centos7 --name install_ok 查看快照virsh snapshot-list centos7
还原快照virsh snapshot-revert centos7 --snapshotname 1516574134 删除快照virsh snapshot-delete centos7 --snapshotname 1516636570
raw不支持做快照,qcow2支持快照,并且快照就保存在qcow2的磁盘文件中
4.7 kvm虚拟机克隆
4.7.1 完整克隆
自动挡:
virt-clone --auto-clone -o web01 -n web02 (完整克隆)
手动挡:
qemu-img convert -f qcow2 -O qcow2 -c web01.qcow2 web03.qcow2
virsh dumpxml web01 >web02.xml
vim web02.xml
#修改虚拟机的名字
#删除虚拟机uuid
#删除mac地址mac add
#修改磁盘路径disk
virsh define web02.xml
virsh start web02
4.7.2 链接克隆
a:生成虚拟机磁盘文件
qemu-img create -f qcow2 -b web03.qcow2 web04.qcow2
b:生成虚拟机的配置文件
virsh dumpxml web01 >web03.xml
vim web03.xml
#修改虚拟机的名字
web03
#删除虚拟机uuid
8e505e25-5175-46ab-a9f6-feaa096daaa4
#删除mac地址
#修改磁盘路径
c:导入虚拟机并进行启动测试
virsh define web03.xml virsh start web03
全自动链接克隆脚本:
[root@kvm01 scripts]# cat link_clone.sh
#!/bin/bash
old_vm=$1
new_vm=$2
#a:生成虚拟机磁盘文件
old_disk=
virsh dumpxml $old_vm|grep "<source file"|awk -F"'" '{print $2}'
disk_tmp=
dirname $old_disk
qemu-img create -f qcow2 -b $old_disk d i s k t m p / {disk_tmp}/ disktmp/{new_vm}.qcow2
#b:生成虚拟机的配置文件
virsh dumpxml o l d v m > / t m p / old_vm >/tmp/ oldvm>/tmp/{new_vm}.xml
#修改虚拟机的名字
sed -ri "s#()(.*)()#\1KaTeX parse error: Undefined control sequence: \3 at position 9: {new_vm}\̲3̲#g" /tmp/{new_vm}.xml
#删除虚拟机uuid
sed -i ‘//d’ /tmp/KaTeX parse error: Expected 'EOF', got '#' at position 14: {new_vm}.xml #̲删除mac地址 sed -i…{new_vm}.xml
#修改磁盘路径
sed -ri “s#()#\1 d i s k t m p / {disk_tmp}/ disktmp/{new_vm}.qcow2\3#g” /tmp/KaTeX parse error: Expected 'EOF', got '#' at position 14: {new_vm}.xml #̲c:导入虚拟机并进行启动测试 …{new_vm}.xml
virsh start ${new_vm}
4.8 kvm虚拟机的桥接网络
默认的虚拟机网络是NAT模式,网段192.168.122.0/24
4.8.1 创建桥接网卡
创建桥接网卡命令 virsh iface-bridge eth0 br0 取消桥接网卡命令 virsh iface-unbridge br0
4.8.2 新虚拟机使用桥接模式
默认NAT模式
virt-install --virt-type kvm --os-type=linux --os-variant rhel7 --name web04 --memory 1024 --vcpus 1 --disk /opt/web04.qcow2 --boot hd --network network=default --graphics vnc,listen=0.0.0.0 --noautoconsole
桥接模式
virt-install --virt-type kvm --os-type=linux --os-variant rhel7 --name web04 --memory 1024 --vcpus 1 --disk /data/web04.qcow2 --boot hd --network bridge=br0 --graphics vnc,listen=0.0.0.0 --noautoconsole
问题1:
如果虚拟机获取不到ip地址:
4.8.3 将已有虚拟机网络修改为桥接模式
a:关机状态下修改虚拟机配置文件:
例如:virsh edit centos7
虚拟机开机之后,修改ip地址为10.0.0.11
上传脚本openstack-mitaka-autoinstall.sh到/root目录
上传镜像:cirros-0.3.4-x86_64-disk.img到/root目录
上传配置文件:local_settings到/root目录
上传openstack_rpm.tar.gz到/root下,
tar xf openstack_rpm.tar.gz -C /opt/ mount /dev/cdrom /mnt
sh /root/openstack-mitaka-autoinstall.sh
大概10-30分钟左右 访问http://10.0.0.11/dashboard 域:default 用户名:admin 密码:ADMIN_PASS
注意: 在windows系统上修改host解析(10.0.0.11 controller)
添加node节点:
修改ip地址 hostnamectl set-hostname compute1
重新登录让新主机名生效 上传openstack_rpm.tar.gz到/root下,
tar xf openstack_rpm.tar.gz -C /opt/ mount /dev/cdrom /mnt
上传脚本openstack_compute_install.sh
sh openstack_compute_install.sh
openstack controller
主控制节点,node节点, kvm宿主机
node节点, kvm宿主机
node节点, kvm宿主机
node节点, kvm宿主机
二、 第二部分 docker容器
- 什么是容器
容器是隔离的环境中运行的一个进程,如果进程结束,容器就会停止,容器的隔离环境,拥有自己的ip地址,系统文件,主机名,进程管理
程序: 代码,软件,命令
进程:正在运行的程序 - 容器和虚拟机的区别
虚拟机: 硬件cpu支持(vt虚拟化),模拟计算硬件,走正常的开机启动
bios开机自检–根据bios启动项–读取硬盘第一个扇区grub,uefi, centos7, 加载内核,启动系统第一个进程/sbin/init systemd
容器: 不需要硬件cpu的支持,共用宿主机内核,启动容器的第一个进程
容器优势: 启动快,性能高,损耗少,轻量级
100虚拟机 100个服务 10宿主机
100容器 100个服务 6宿主机 - docker-ce的安装
主机名 内存 ip
docker01 2G 10.0.0.11
docker02 2G 10.0.0.12
#安装docker-ce
wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
sed -i ‘s+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+’ /etc/yum.repos.d/docker-ce.repo
yum install docker-ce -y
systemctl enable docker
systemctl start docker
#验证
[root@docker01 yum.repos.d]# docker version
Client: Docker Engine - Community
Version: 19.03.5
API version: 1.40
Go version: go1.12.12
Git commit: 633a0ea
Built: Wed Nov 13 07:25:41 2019
OS/Arch: linux/amd64
Experimental: false
4. docker主要内容
docker是一个cs架构, docker主要:镜像 容器 仓库 网络 存储 监控
docker是一个软件的打包技术.
docker run -d -p 80:80 nginx:latest
run 创建并启动一个容器
-d 放后台启动
-p 端口映射
nginx:latest docker镜像名称
5. docker镜像常用命令
拉取/下载镜像
docker pull 镜像名称 [拉取镜像(下载镜像),注意版本]
docker push 镜像名称 [推送镜像(上传镜像)]
构建镜像
docker build -t 镜像名称
查看已经下载的镜像
docker image ls
删除本地镜像
docker rmi 镜像名称
镜像导入/导出
docker import 导入镜像
• -c :应用docker 指令创建镜像;
• -m :提交时的说明文字
docker load -i 加载本地镜像
docker save -o 导出路径 镜像id
例子:docker save centos:7 -o docker_centos7.tar.gz
搜索镜像
docker search 搜索镜像, 优先选官方,stars数量多
例子: docker load -i docker_nginx.tar.gz
给镜像打标签
docker tag 镜像id 新镜像名称:版本
查看镜像创建历史
docker history 查看指定镜像的创建历史
• -H :以可读的格式打印镜像大小和日期,默认为true;
• --no-trunc :显示完整的提交记录;
• -q :仅列出提交记录ID。
- docker容器的常用命令
运行容器
docker run 镜像标识|镜像名称
( -v -e --privilege –network=host)
例子:docker run -d -it -p 80:80 nginx:latest
-d表示后台运行 -p表示宿机与容器间的映射端口 --name表示给容器指定的命名
创建容器
docker create 创建容器 –name
容器的启动、关闭、重启
docker start 启动容器
docker stop 停止容器
docker restart 重启容器
docker kill 强制停止容器
查看正在运行的容器
docker ps 查看容器列表
docker ps -a 查看所有容器 包括未运行的
docker ps -q 查看容器的标识
docker rm 删除容器
批量删除所有容器 docker rm -fdocker ps -a -q
查看容器日志
docker logs -f 容器id 查看容器的控制台输出
-f表示查看最后几行
进入容器
docker exec 进入正在运行的容器(分配一个新终端)
例子: docker exec -it 容器id/容器名字 /bin/bash(/bin/sh)
docker attach 进入正在运行的容器(使用相同的终端),偷偷离开的快捷键ctrl +p,ctrl +q
容器想要放在后台一直运行的化,那么容器的初始命令,必须夯住(前台运行),否则容器就会退出.
前台运行
nginx -g ‘daemon off;’
/usr/sbin/php-fpm –nodaemonize
启动、关闭、删除、重命名容器
docker start 容器id 启动容器
docker stop 容器id 关闭容器
docker rm 容器id 删除容器
docker rename 容器id 重命名容器
查看容器
docker top 查看容器中运行的进程信息,支持 ps 命令参数
docker container diff 查看容器中发生变化的文件
docker container inspect 查看容器的属性
docker container port 查看容器做了哪些随机端口
docker container stats 查看容器的所耗信息(–no-stream)
docker system df 查看容器的使用情况(整体磁盘的使用情况)
docker system info 查看整个docker系统的信息[容器的运行环境:runc]
容器的导入导出
docker commit 把容器提交为镜像
docker container export 把容器导出为镜像压缩包
[docker export 3984da8164fb >docker_test.tar.gz(export导出的镜像压缩包只能用inport导入)]
容器的拷贝、挂起、释放、移除、修改、清理
docker cp 用于容器与宿主机之间的数据拷贝
docker container pause 挂起容器
docker container upause 释放挂起的容器
docker container prune 移除所有停止的容器
docker container update 修改容器的属性,(–memory --memory-swap)
docker container wait 等一个或多个容器停止,打印出退出代码
docker system prune 清理没有使用的数据,包括镜像数据,已经停止的容器
docker system events 获取docker系统实时事件,不包括容器内的。 - docker端口映射
docker run
-p 宿主机端口:容器端口
-p 宿主机ip1:宿主机端口:容器端口 (多个容器同时使用80端口)
-p 宿主机ip1::容器端口 随机端口映射
-p 宿主机ip1::容器端口/udp 使用udp协议做随机端口映射
-p 80:80 -p 3306:3306
-p 1111-1119:1111-1119 端口范围映射
-P 自动随机端口映射 - docker数据卷
docker run
-v 宿主机绝对目录:容器目录
-v 容器目录 #创建一个随机卷,来持久化容器的目录下的数据
-v 卷名:容器目录 #创建一个固定名字的卷,来持久化容器的目录下的数据
–volumes-from 跟某一个容器挂载所有相同的卷
小练习: 只启动一个nginx容器,要求访问80端口,出现nginx默认欢迎首页,访问81端口,出现小鸟飞飞. - 手动制作docker镜像
制作一个基于centos7系统的nginx镜像(单服务)
1:手动做镜像
a:启动一个基础容器,安装服务
echo “192.168.15.253 mirrors.aliyun.com” >>/etc/hosts
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
yum install nginx -y
rm -fr /usr/share/nginx/html/index.html
echo ‘web01’ >/usr/share/nginx/html/index.html
b:将安装好服务的容器提交为镜像
docker container commit 0f65a315c159 centos7_nginx:v1
c:测试镜像
docker run -d -p 82:80 centos7_nginx:v1 nginx -g ‘daemon off;’
制作一个支持ssh登录的镜像
docker run -it -p 1022:22 centos:7
echo “192.168.15.253 mirrors.aliyun.com” >>/etc/hosts
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum install openssh-server -y
systemctl start sshd
cat /usr/lib/systemd/system/sshd.service
/usr/sbin/sshd -D
ls /etc/ssh/
cat /usr/lib/systemd/system/sshd-keygen.service
/usr/sbin/sshd-keygen
rpm -qa|grep initscripts
yum install initscripts -y
/usr/sbin/sshd-keygen
ls /etc/ssh/
/usr/sbin/sshd
ctrl+p ctrl+q 悄悄离开
docker ps -a -l
ssh root010.0.0.11 -p 1022
需要密码,然后ctrl+c退出
docker attach 6a0ece9b8778(这个是自己的容器ID)
进入容器
echo '123456 ’ |passwd --stdin root(设置密码)
ctrl+p ctrl+q 悄悄离开
ssh roota10.0.0.11 -p 1022
ps -ef
logout
docker attach 6a0ece9b8778
exit
宿主机:
docker ps -a -l
将容器提交为一个镜像
docker commit 6a0ece9b8778 centos7_sshd: v1
测试镜像
docker run -d -p 1023:22 centos7_sshd:v1 /usr/sbin/sshd -D
docker ps -a-l
ssh root010.0.0.11 -p 1023
制作一个基于centos7系统的Nginx+sshd双服务镜像
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
yum install Nginx -y
yum install openssh-server -y
yum install initscripts -y
/usr/sbin/sshd-keygen
echo ‘123456’|passwd --stdin root
提交镜像之前写脚本
vim /init.sh
Nginx
/usr/sbin/sshd -D
提交镜像
docker commit f784da45ec97 centos_Nginx_sshd: v1
(已经提交了但是没写脚本怎么办?
重新弄一个容器写脚本
/usr/sbin/sshd -D
制作一个基于centos7系统的kod网盘的镜像(多服务)
1:启动一个centos7_Nginx:v1,再安装PHP
echo ‘192.168.12.201 mirrors.aliyun.com’ >>/etc/hosts
yum install PHP-fpm PHP-gd PHP-mbstring -y
vi /etc/PHP-fpm.d/www.conf
; RPM: apache Choosed to be able to access some dir as httpd
user = Nginx
; RPM: Keep a group allowed to write in log dir.
group = Nginx
启动:
PHP-fpm -D
cd /etc/Nginx/conf.d/
vi default.conf
server {
listen 80;
server_name _;
root /html;
index index.PHP index.html index.htm;
location ~ .PHP$ {
root /html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.PHP;
fastcgi_param SCRIPT_FILENAME /html$fastcgi_script_name;
include fastcgi_params;
}
}
mkdir /html
cd /html
curl -o kodexplorer4.40.zip http://192.168.15.253/kodexplorer4.40.zip
yum install unzip -y
unzip kodexplorer4.40.zip
vi /init.sh
#!/bin/bash
Nginx
/usr/sbin/PHP-fpm --nodaemonize
2:把安装好服务的容器,提交为镜像
docker commit 47208e3e3796 kod:v2
3:测试镜像的功能
docker run -d -p 83:80 kod:v2 /bin/bash /init.sh
10. 自动制作docker镜像
镜像: 中药
dockerfile: 配方
dockerfile常用指令
FROM 基础镜像
RUN 制作镜像过程中需要的执行命令(安装服务)
CMD 容器启动的时候执行的初始命令,容易被替换(启动服务)
ENTRYPOINT 容器启动的时候执行的初始命令,不能被替换,如果同时使用CMD和ENTRYPOINT,cmd命令将作为ENTRYPOINT命令的参数
ADD 把dockerfile当前目录下的文件拷贝到容器中(自动解压tar包)
copY 把dockerfile当前目录下的文件拷贝到容器中(不解压tar包)
workdir 指定容器的默认工作目录
EXPOSE 镜像要暴露的端口
VOLUME 持久化卷
ENV 环境变量(ssh的密码,数据库的密码)
LABEL 镜像的属性标签
MAINTAINER 管理者标识
根据dockerfile自动构建镜像的思路
a:手动制作docker镜像,记录历史命令
b:根据历史命令编写dockerfile文件
c:docker build构建docker镜像
d:测试镜像的功能
dockerfile单服务例子1:
FROM centos:6.9
RUN echo ‘192.168.19.200 mirrors.aliyun.com’ >>/etc/hosts
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.
aliyun.com/repo/epel-6.repo
RUN yum install Nginx -y
CMD [“Nginx”,"-g",“daemon off;”]
dockerfile多服务例子2:
FROM centos6.9_Nginx:v1
RUN yum install PHP-fpm PHP-gd PHP-mbstring -y
ADD www.conf /etc/PHP-fpm.d/www.conf
ADD default.conf /etc/Nginx/conf.d/default.conf
RUN mkdir /html
workdir /html
RUN curl -o kodexplorer4.40.zip http://192.168.19.200/191127/kodexplorer4.40.zip
RUN yum install unzip -y
RUN unzip kodexplorer4.40.zip
RUN chown -R Nginx:Nginx .
ADD init.sh /init.sh
CMD ["/bin/bash","/init.sh"]
vi /init.sh
#!/bin/bash
service PHP-fpm start
Nginx -g ‘daemon off;’
dockerfile使用环境变量的例子:
FROM centos:7
RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
RUN yum install Nginx openssh-server initscripts -y
RUN /usr/sbin/sshd-keygen
ADD init.sh /init.sh
ENTRYPOINT ["/bin/bash","/init.sh"]
vi init.sh
#!/bin/bash
if [ -z $SSH_PWD ];then
SSH_PWD=$1
fi
echo $SSH_PWD|passwd --stdin root
Nginx
/usr/sbin/sshd -D
11. docker镜像的分层(复用,节省空间)
- dockerfile的优化
优化原则:
构建的镜像尽可能小,构建速度尽可能快
a: 使用体积小的linux镜像alpine作为基础镜像
[linux发行版最大的区别:安装包不一样、配置文件路径不一样、
Centos:yum rpm (red package manager ) 网卡配置路径
Suse:zypper
Ubuntu:apt-get /etc/network/interfaces /etc/int Nginx rzsz
Alpine:apk
sed -i ‘s/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g’/etc/apk/ repositories
apk add Nginx
Centos:编译器 gcc glibc jdk.rpm jdk.tar.gz
Alpine:编译器 musl libc
选择:alpine Debian/ubunto centos]
b:尽可能的清理无用的缓存文件(尽可能把多个RUN合并)
c:修改dockerfile的时候,尽可能把修改的内容放在最后
d:使用.dockerignore忽略构建docker镜像时,不需要的文件
13. 容器间的互联
容器之间通讯,面临的问题
容器IP地址按顺序分配,不知道要通讯的容器IP是多少
docker run –link docker run --name MysqL-server -it
-e MysqL_DATABASE=“zabbix”
-e MysqL_USER=“zabbix”
-e MysqL_PASSWORD=“zabbix_pwd”
-e MysqL_ROOT_PASSWORD=“root_pwd”
-d MysqL:5.7
–character-set-server=utf8 --collation-server=utf8_bin
docker run --name zabbix-java-gateway -t
-d zabbix/zabbix-java-gateway:latest
docker run --name zabbix-server-MysqL -t
-e DB_SERVER_HOST=“MysqL-server”
-e MysqL_DATABASE=“zabbix”
-e MysqL_USER=“zabbix”
-e MysqL_PASSWORD=“zabbix_pwd”
-e MysqL_ROOT_PASSWORD=“root_pwd”
-e ZBX_JAVAGATEWAY=“zabbix-java-gateway”
–link MysqL-server:MysqL
–link zabbix-java-gateway:zabbix-java-gateway
-p 10051:10051
-d zabbix/zabbix-server-MysqL:latest
docker run --name zabbix-web-Nginx-MysqL -t
-e DB_SERVER_HOST=“MysqL-server”
-e MysqL_DATABASE=“zabbix”
-e MysqL_USER=“zabbix”
-e MysqL_PASSWORD=“zabbix_pwd”
-e MysqL_ROOT_PASSWORD=“root_pwd”
–link MysqL-server:MysqL
–link zabbix-server-MysqL:zabbix-server
-p 80:80
-d zabbix/zabbix-web-Nginx-MysqL:latest
14. 单机版的容器编排
yum install docker-compose -y(需要epel源)
docker-compose:批量管理一组容器
批量启动
批量关闭
批量重启
docker-compose up -d 创建并启动一组容器
docker-compose down 停止并删除一组容器
docker-compose start 批量启动
docker-compose stop 批量停止
docker-compose restart 重启
docker-compose scale 设置服务的容器数
Yaml文件
缩进
运行容器的名字(单方向)
version: ‘3’
services:
MysqL-server:
image: MysqL:5.7
restart: always
environment:
MysqL_ROOT_PASSWORD: root_pwd
MysqL_DATABASE: zabbix
MysqL_USER: zabbix
MysqL_PASSWORD: zabbix_pwd
command: --character-set-server=utf8 --collation-server=utf8_bin
zabbix-java-gateway:
image: zabbix/zabbix-java-gateway:latest
restart: always
zabbix-server:
depends_on:
- MysqL-server
image: zabbix/zabbix-server-MysqL:latest
restart: always
environment:
DB_SERVER_HOST: MysqL-server
MysqL_DATABASE: zabbix
MysqL_USER: zabbix
MysqL_PASSWORD: zabbix_pwd
MysqL_ROOT_PASSWORD: root_pwd
ZBX_JAVAGATEWAY: zabbix-java-gateway
ports:
- “10051:10051”
zabbix-web-Nginx-MysqL:
depends_on:
- zabbix-server
image: zabbix/zabbix-web-Nginx-MysqL:latest
ports:
- “80:80”
restart: always
environment:
DB_SERVER_HOST: MysqL-server
MysqL_DATABASE: zabbix
MysqL_USER: zabbix
MysqL_PASSWORD: zabbix_pwd
MysqL_ROOT_PASSWORD: root_pwd
docker-compose up -d 启动服务
docker-compose down 停止服务
15. 私有仓库docker-registry
.上传镜像的步骤:
1:打标签
2: docker push. 上传
#启动私有仓库
docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry registry :latest
#镜像地址
Nginx:1.15 官方仓库的官方镜像
Nginx/Nginx:1.15 官方仓库的用户镜像
daocloud.io/Nginx/Nginx:1.15 私有仓库的镜像
#上传镜像
docker tag alpine:3.9 10.0.0.11:5000/alpine:3.9
docker image push 10.0.0.11:5000/alpine:3.9
#第一次上传镜像会报错
vim /etc/docker/daemon.json
{
“registry-mirrors”: [“https://registry.docker-cn.com”],
“insecure-registries”: [“10.0.0.11:5000”]
}
systemctl restart docker
docker image push 10.0.0.11:5000/alpine:3.9
#下载镜像
docker image pull 10.0.0.11:5000/alpine:3.9
16. 企业级私有仓库harbor(docker-compose)
#下载安装器
[root@docker02 ~]# cd /opt/
[root@docker02 opt]# wget http://192.168.15.253/harbor-offline-installer-v2.1.0.tgz
#解压
[root@docker02 opt]# tar xf harbor-offline-installer-v2.1.0.tgz
#修改配置文件
[root@docker02 opt]# cd harbor/
[root@docker02 harbor]# curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
[root@docker02 harbor]# yum -y install docker-compose
[root@docker02 harbor]# cp harbor.yml.tmpl harbor.yml
[root@docker02 harbor]# vim harbor.yml
hostname: 10.0.0.12
注释https的配置
harbor_admin_password: 123456
#执行安装脚本
./install.sh
[root@docker01 ~]$vim /etc/docker/daemon.json
{
“registry-mirrors”: [" https://registry.docker-cn.com"],
“insecure-registries”: [" 10.0.0.12"]
}
[root@docker01 ~]$systemctl restart docker
[root@docker01 ~]
d
o
c
k
e
r
t
a
g
a
l
p
i
n
e
:
3.910.0.0.12
/
l
i
b
r
a
r
y
/
a
l
p
i
n
e
:
3.9
[
r
o
o
t
@
d
o
c
k
e
r
01
]
docker tag alpine:3.9 10.0.0.12/library/alpine:3.9 [root@docker01 ~]
dockertagalpine:3.910.0.0.12/library/alpine:3.9[root@docker01 ]docker login 10.0.0.12
[root@docker01 ~]$docker push 10.0.0.12/library/alpine:3.9
安全上传镜像(使用证书)
[root@docker02 opt]# mkdir cert
[root@docker02 opt]# cd cert
[root@docker02 cert]# pwd
/opt/cert
[root@docker02 cert]# wget http://192.168.15.253/blog.oldqiang.com.zip
[root@docker02 cert]# unzip blog.oldqiang.com.zip
[root@docker02 cert]# ls Nginx/
1_blog.oldqiang.com_bundle.crt 2_blog.oldqiang.com.key
[root@docker02 cert]# cd /opt/harbor/
[root@docker02 harbor]# pwd
/opt/harbor
[root@docker02 harbor]# cd /opt/
[root@docker02 opt]# cd cert
[root@docker02 cert]# ls
Apache blog.oldqiang.com.csr blog.oldqiang.com.zip IIS Nginx Tomcat
为harbor配置h#修改harbor.yml
[root@docker02 harbor]# vim harbor.yml
#配置域名
hostname: blog.oldqiang.com
#配置证书
https:
port: 443
certificate: /opt/certs/Nginx/1_blog.oldqiang.com_bundle.crt
private_key: /opt/certs/Nginx/2_blog.oldqiang.com.key
#重新执行安装脚本
./install.sh
[root@docker01 ~]# vim /etc/docker/daemon.json
[root@docker01 ~]# systemctl restart docker
[root@docker01 ~]# vim /etc/hosts
10.0.0.12 blog.oldqiang.com
[root@docker01 ~]# docker pull blog.oldqiang.com/library/alpine:3.9
docker images|grep Zabbix
docker tag zabbix/zabbix-server-MysqL:latest blog.oldqiang.com/zabbix/zabbix-server-MysqL:latest
docker login blog.oldqiang.com
docker pushblog.oldqiang.com/zabbix/zabbix-server-MysqL:latest
rm -rf/root/.docker/config.json
docker login blog.oldqiang.com
docker pull blog.oldqiang.com/zabbix/zabbix-server-MysqL:latest
docker-registry和harbor的区别,为什么优先选择harbor?
docker-registry 管理不方便,相对来说比较省资源
harbor 友好的web界面,功能更完善
17. docker基础网络
四种基础网络类型https证书
bridge 默认类型 NAT模式 访问外网需要端口映射
host host类型,使用宿主机网络,网络性能最高,不能有端口冲突,速度最高
container 容器类型。使用其他容器共用网络,k8s中使用
none 没有网络,上不了外网 不给IP地址
创建自定义网络
docker network create -d bridge --subnet 172.18.0.0/16 --gateway 172.18.0.1 oldqiang
-d 指定网络类型
–subnet 子网
–gateway 网关
18. 跨宿主机容器间的通讯之macvlan
macvlan类似与虚拟机的桥接网络
macvlan:容器拥有和宿主机同一网段的IP,不能检测IP地址,需手动管理IP地址分配
#创建网络
docker network create -d macvlan --subnet 10.0.0.0/24 --gateway 10.0.0.2 -o parent=eth0 macvlan_1
#启动容器
docker run -it --network macvlan_1 --ip 10.0.0.105 alpine:3.9
19. 跨宿主机容器间的通讯之overlay
overlay: IP存储在consul服务里面,使用该网络的容器,默认有两张网卡,eth0:容器之间通讯使用,eth1:访问外网,可实现容器之间的双向通讯
docker03上: consul存储ip地址的分配
docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap
docker01、02上:
vim /etc/docker/daemon.json
{
“cluster-store”: “consul://10.0.0.13:8500”,
“cluster-advertise”: “10.0.0.11:2376”
}
systemctl restart docker
2)创建overlay网络
docker network create -d overlay --subnet 172.26.0.0/16 --gateway 172.26.0.1 ol1
3)启动容器测试
docker run -it --network ol1 --name oldboy01 alpine:3.9 /bin/sh
每个容器有两块网卡,eth0实现容器间的通讯,eth1实现容器访问外网
20. docker容器的监控
Linux监控:实现事前预警,
监控工具:
zabbix 容易使用,功能强大 监控传统业务,监控主要靠模板,不好监控容器,
nagios 不保存历史数据,
catic 保存历史数据,每五分钟监控一次,
openfalcon 不好用,上手程度不如zabbix
监控软件:
Prometheus 普罗米修斯,
docker使用,监控容器业务,
功能:实现对数据的处理,目前不能替代zabbix,要监控就得有exporter,
(exporter主要作用:采集数据提供HTML页面,页面有采集好的数据,) [启动Prometheus时自动生成prometheus.yml配置文件(target),]
作用:最终实现数据的集中处理。
Prometheus内置tsdb时间序列数据库,以时间作为索引,方便快速查询,
同时支持外置数据库,
需要在Prometheus中指定alterManager的IP和端口,实现报警(邮件报警、微信报警、钉钉报警,)
[报警规则:rule.yml文件]
官网下载:Prometheus.io/download
#配置普罗米修斯:prometheus节点:docker03
[root@oldboyedu ~]# cd /opt/
[root@oldboyedu opt]# wget
http://192.168.15.253/prometheus-2.23.0.linux-amd64.tar.gz
[root@oldboyedu opt]# tar xf prometheus-2.23.0.linux-amd64.tar.gz
[root@oldboyedu opt]# cd prometheus-2.23.0.linux-amd64/
[root@oldboyedu prometheus-2.23.0.linux-amd64]# vim prometheus.yml
#启动prometheus
[root@oldboyedu prometheus-2.23.0.linux-amd64]# ./prometheus --config.file=“prometheus.yml” &
#客户端节点 docker01\02
#启动node-exporter
docker run -d -p 9100:9100 -v “/:/host:ro,rslave” --name=node_exporter quay.io/prometheus/node-exporter --path.rootfs /host
#启动cadvisor
docker run --volume=/:/rootfs:ro --volume=/var/run:/var/run:rw --volume=/sys:/sys:ro --volume=/var/lib/docker/:/var/lib/docker:ro --publish=8080:8080 --detach=true --name=cadvisor google/cadvisor:latest
-p (publish)
-v (volume)
-d (detach)
浏览器访问:10.0.0.13:9090
prometheus节点
cd prometheus-2.12.0.linux-amd64/
vim prometheus.yml
{scrape_configs:
- job_name: ‘prometheus’
static_configs:- targets: [‘localhost:9090’]
- job_name: ‘cadvisor’
static_configs:- targets: [‘10.0.0.11:8080’,‘10.0.0.12:8080’]
- job_name: ‘node_exporter’
static_configs:- targets: [‘10.0.0.11:9100’,‘10.0.0.12:9100’]} (静态报警)
{ - job_name: ‘cadvisor’
file_sd_configs: - files:
- job/server.json
refresh_interval: 10s }(动态报警)
[root@oldboyedu prometheus-2.23.0.linux-amd64]# mkdir job
[root@oldboyedu prometheus-2.23.0.linux-amd64]# vi job/server.json
[
{
“targets”: [" 10.0.0.11:8080"," 10.0.0.12:8080"]
}
]
[root@oldboyedu prometheus-2.23.0.linux-amd64]# ps -ef |grep prome
root 27748 26657 0 10:46 pts/0 00:00:02 ./prometheus --config.file=prometheus.yml
root 27987 26657 0 11:18 pts/0 00:00:00 grep --color=auto prome
[root@oldboyedu prometheus-2.23.0.linux-amd64]# kill 26657
[root@oldboyedu prometheus-2.23.0.linux-amd64]# ./prometheus --config.file=“prometheus.yml” &
- job/server.json
- targets: [‘10.0.0.11:9100’,‘10.0.0.12:9100’]} (静态报警)
#启动prometheus
./prometheus --config.file=“prometheus.yml” &
浏览器访问:10.0.0.13:9090
alterManager报警:
思路:alterManager配置收件人和发件人
普罗米修斯上配置报警规则rule.yml(重启生效)
Grafana(开源的数据可视化工具)
普罗米修斯节点:
#安装grafana
yum localinstall grafana-6.3.3-1.x86_64.rpm -y
systemctl start grafana-server.service
systemctl enable grafana-server.service
#访问grafana http://10.0.0.13:3000,默认账号admin:admin
插件;zabbix的插件
数据源:要写上普罗米修斯的地址
作用:优化web界面
新建数据源导入dashboard模板
保存并退出:
保存后我们发现普罗米修斯数据源添加成功:
Dashboard:出图模板(grafan.doc官网下载)
浏览器访问grafana官网:grafana.com/docs
上传刚刚下载的json文件
实现监控nodeExporter:
实现监控cadvisor:
下载json文件:
在普罗米修斯中的图:
三、 第三部分:k8s
- k8s集群的安装
1.1 k8s的架构
一个master对应一群node
Kubectl:用户通过这个工具去调用api-server管理集群
Master:
api-server :相当于k8s的网关,所有的请求都得经过api-server转发
scheduler:使用调度算法将请求调度到某一个node节点
controller:控制器,维护k8s资源 删除增加等
etcd:存储资源对象 服务注册 发现
node:
docker:运行容器的环境 即容器引擎
kubelet:每个node节点都有一个,在node资源相关指令就由kubelet来执行。扫描etcd获取相关指令,扫描请求。一旦发现请求,就在node执行。
Kube-proxy: 代理服务
Pod: 最小单元 ,内部是容器 。k8s不直接管理容器,是通过管理pod来管理容器
Fluented:日志收集服务
Service:
Scheduler的调度:
请求交给api-server,然后将指令数据存储在etcd,node节点的kubelet扫描etcd,从etcd之中获取相关数据信息,然后再node节点执行相关的指令
ReplicationControler/replicaset: rs 副本控制器 管理pod
Deployment:管理rs与pod
StatefulSet:
Daemonset:确保多节点部署同一个pod.
核心服务:API server (解析执行任何的k8s命令)[所有k8s组都受API server控制,调用docker创建容器]
etcd :数据库 (存储k8s中创建的资源)[非关系型数据库]
Schedule:调度器 (创建容器时,选择合适的目前资源较多,负载不是很高的,剩余内存较多的节点)
node节点安装一个服务(kubelet:调用docker来实现对容器的管理,随时可以接受API server的远程控制)
所有容器封装在pod中
API server调用kubelet创建容器–kubelet调用docker
监管的角色(controller manager—控制管理,检测容器数量与状态,确保数量不减少)
k8s与cadvisor谷歌公司开发
Kube-proxy作用:实现负载均衡
Plugin network网络插件
Calico 3层acl
Fiannel(简单、高效、容器达到跨宿主机通讯)
k8s构建:
master:etcd api-server controller-manager scheduler
node : kubelet kube-proxy
kubelet作用:接受api-server指令,调用docker启动容器
除了核心组件,还有一些推荐的Add-ons:(附加组件是可选的)
组件名称 说明
kube-dns 负责为整个集群提供DNS服务
Ingress Controller 为服务提供外网入口
Heapster 提供资源监控
Dashboard 提供GUI(web界面)
Federation 提供跨可用区的集群(联邦集群,管理多套环境)
Fluentd-elasticsearch 提供集群日志采集、存储与查询
Kubectl命令:
create
describe
edit
get
exec
scale
set image
Run 默认创建deployment
expose
rolling-update
rolllout
logs
1.2 k8s的架构(二进制安装)
1.3 k8s的安装(二进制安装)
环境准备(修改ip地址,主机名,host解析)
做hosts解析和秘钥推送(四个节点都要做)
vim /etc/hosts
10.0.0.11 k8s-master
10.0.0.12 k8s-node1
10.0.0.13 k8s-node2
10.0.0.14 k8s-node3
ssh-keygen
ssh-copy-id root@10.0.0.11
ssh-copy-id root@10.0.0.12
ssh-copy-id root@10.0.0.13
ssh-copy-id root@10.0.0.14
主机 ip 内存 软件
k8s-master 10.0.0.11 1g etcd,api-server,controller-manager,scheduler
k8s-node1 100.0.12 2g etcd,kubelet,kube-proxy,docker,flannel
k8s-node2 10.0.0.13 2g ectd,kubelet,kube-proxy,docker,flannel
k8s-node3 10.0.0.14 1g kubelet,kube-proxy,docker,flannel
1.3.1 颁发证书:
K8s组件都是通过http协议,节点和节点之间通讯需要证书
etcd–etcd—etcd
api-server – etcd
flanneld –> etcd
api-server –> kubelet
api-server -> kube-proxy
6443 https
api-server –> controller-manager
api-server -> scheduler
8080 http 127.0.0.1
准备证书颁发工具[openssl生成ca.crt证书,生成xxx.csr请求文件,生成xxx.key私钥,比较麻烦,现在使用cfssl生成证书比较简单,cfssl-certinfo验证证书的有效期]
在node3节点上
[root@k8s-node3 ~]# mkdir /opt/softs
[root@k8s-node3 ~]# cd /opt/softs
[root@k8s-node3 softs]# rz -E
[root@k8s-node3 softs]# ls
cfssl cfssl-certinfo cfssl-json
[root@k8s-node3 softs]# chmod +x /opt/softs/*
[root@k8s-node3 softs]# ln -s /opt/softs/* /usr/bin/
[root@k8s-node3 softs]# mkdir /opt/certs
[root@k8s-node3 softs]# cd /opt/certs
编辑ca证书配置文件
vi /opt/certs/ca-config.json
i{
“signing”: {
“default”: {
“expiry”: “175200h”
},
“profiles”: {
“server”: {
“expiry”: “175200h”,
“usages”: [
“signing”,
“key encipherment”,
“server auth”
]
},
“client”: {
“expiry”: “175200h”,
“usages”: [
“signing”,
“key encipherment”,
“client auth”
]
},
“peer”: {
“expiry”: “175200h”,
“usages”: [
“signing”,
“key encipherment”,
“server auth”,
“client auth”
]
}
}
}
}
编辑ca证书请求配置文件
vi /opt/certs/ca-csr.json
i{
“CN”: “kubernetes-ca”,
“hosts”: [
],
“key”: {
“algo”: “rsa”,
“size”: 2048
},
“names”: [
{
“C”: “CN”,
“ST”: “beijing”,
“L”: “beijing”,
“O”: “od”,
“OU”: “ops”
}
],
“ca”: {
“expiry”: “175200h”
}
}
生成CA证书和私钥
[root@k8s-node3 certs]# cfssl gencert -initca ca-csr.json | cfssl-json -bare ca -
[root@k8s-node3 certs]# ls
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem
1.3.2 部署etcd集群
主机名 ip 角色
k8s-master 10.0.0.11 etcd lead
k8s-node1 10.0.0.12 etcd follow
k8s-node2 10.0.0.13 etcd follow
颁发etcd节点之间通信的证书
vi /opt/certs/etcd-peer-csr.json
i{
“CN”: “etcd-peer”,
“hosts”: [
“10.0.0.11”,
“10.0.0.12”,
“10.0.0.13”
],
“key”: {
“algo”: “rsa”,
“size”: 2048
},
“names”: [
{
“C”: “CN”,
“ST”: “beijing”,
“L”: “beijing”,
“O”: “od”,
“OU”: “ops”
}
]
}
[root@k8s-node3 certs]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer etcd-peer-csr.json | cfssl-json -bare etcd-peer
[root@k8s-node3 certs]# ls etcd-peer*
etcd-peer.csr etcd-peer-csr.json etcd-peer-key.pem etcd-peer.pem
安装etcd服务
在k8s-master,k8s-node1,k8s-node2上
yum install etcd -y
#在node3上发送证书到/etc/etcd目录
[root@k8s-node3 certs]# scp -rp *.pem root@10.0.0.11:/etc/etcd/
[root@k8s-node3 certs]# scp -rp *.pem root@10.0.0.12:/etc/etcd/
[root@k8s-node3 certs]# scp -rp .pem root@10.0.0.13:/etc/etcd/
#所有节点
[root@k8s-master ~]# chown -R etcd:etcd /etc/etcd/.pem
#master节点
[root@k8s-master ~]# grep -Ev ‘^$|#’ /etc/etcd/etcd.conf
ETCD_data_dir="/var/lib/etcd/"
ETCD_LISTEN_PEER_URLS=“https://10.0.0.11:2380”
ETCD_LISTEN_CLIENT_URLS=“https://10.0.0.11:2379,http://127.0.0.1:2379”
ETCD_NAME=“node1”
ETCD_INITIAL_ADVERTISE_PEER_URLS=“https://10.0.0.11:2380”
ETCD_ADVERTISE_CLIENT_URLS=“https://10.0.0.11:2379,http://127.0.0.1:2379”
ETCD_INITIAL_CLUSTER=“node1=https://10.0.0.11:2380,node2=https://10.0.0.12:2380,node3=https://10.0.0.13:2380”
ETCD_INITIAL_CLUSTER_TOKEN=“etcd-cluster”
ETCD_INITIAL_CLUSTER_STATE=“new”
ETCD_CERT_FILE="/etc/etcd/etcd-peer.pem"
ETCD_KEY_FILE="/etc/etcd/etcd-peer-key.pem"
ETCD_CLIENT_CERT_AUTH=“true”
ETCD_TRUSTED_CA_FILE="/etc/etcd/ca.pem"
ETCD_AUTO_TLS=“true”
ETCD_PEER_CERT_FILE="/etc/etcd/etcd-peer.pem"
ETCD_PEER_KEY_FILE="/etc/etcd/etcd-peer-key.pem"
ETCD_PEER_CLIENT_CERT_AUTH=“true”
ETCD_PEER_TRUSTED_CA_FILE="/etc/etcd/ca.pem"
ETCD_PEER_AUTO_TLS=“true”
#node1和node2需修改
ETCD_LISTEN_PEER_URLS=“https://10.0.0.11:2380”
ETCD_LISTEN_CLIENT_URLS=“https://10.0.0.11:2379,http://127.0.0.1:2379”
ETCD_NAME=“node1”
ETCD_INITIAL_ADVERTISE_PEER_URLS=“https://10.0.0.11:2380”
ETCD_ADVERTISE_CLIENT_URLS=“https://10.0.0.11:2379,http://127.0.0.1:2379”
#3个etcd节点同时启动
systemctl start etcd
systemctl enable etcd
#验证
[root@k8s-master ~]# etcdctl member list
1.3.3 master节点的安装
安装api-server服务
上传kubernetes-server-linux-amd64-v1.15.4.tar.gz到node3上,然后解压
[root@k8s-node3 softs]# ls
cfssl cfssl-certinfo cfssl-json kubernetes-server-linux-amd64-v1.15.4.tar.gz
[root@k8s-node3 softs]# tar xf kubernetes-server-linux-amd64-v1.15.4.tar.gz
[root@k8s-node3 softs]# ls
cfssl cfssl-certinfo cfssl-json kubernetes kubernetes-server-linux-amd64-v1.15.4.tar.gz
[root@k8s-node3 softs]# cd /opt/softs/kubernetes/server/bin/
[root@k8s-node3 bin]# rm -rf *.tar *_tag
[root@k8s-node3 bin]# scp -rp kube-apiserver kube-controller-manager kube-scheduler kubectl root@10.0.0.11:/usr/sbin/
签发client证书
[root@k8s-node3 bin]# cd /opt/certs/
[root@k8s-node3 certs]# vi /opt/certs/client-csr.json
i{
“CN”: “k8s-node”,
“hosts”: [
],
“key”: {
“algo”: “rsa”,
“size”: 2048
},
“names”: [
{
“C”: “CN”,
“ST”: “beijing”,
“L”: “beijing”,
“O”: “od”,
“OU”: “ops”
}
]
}
[root@k8s-node3 certs]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client-csr.json | cfssl-json -bare client
[root@k8s-node3 certs]# ls client*
client.csr client-csr.json client-key.pem client.pem
签发kube-apiserver证书
[root@k8s-node3 certs]# vi /opt/certs/apiserver-csr.json
i{
“CN”: “apiserver”,
“hosts”: [
“127.0.0.1”,
“10.254.0.1”,
“kubernetes.default”,
“kubernetes.default.svc”,
“kubernetes.default.svc.cluster”,
“kubernetes.default.svc.cluster.local”,
“10.0.0.11”,
“10.0.0.12”,
“10.0.0.13”
],
“key”: {
“algo”: “rsa”,
“size”: 2048
},
“names”: [
{
“C”: “CN”,
“ST”: “beijing”,
“L”: “beijing”,
“O”: “od”,
“OU”: “ops”
}
]
}
#注意10.254.0.1为clusterIP网段的第一个ip,做为pod访问api-server的内部ip,oldqiang在这一块被坑了很久
[root@k8s-node3 certs]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server apiserver-csr.json | cfssl-json -bare apiserver
[root@k8s-node3 certs]# ls apiserver*
apiserver.csr apiserver-csr.json apiserver-key.pem apiserver.pem
配置api-server服务
master节点
#拷贝证书
[root@k8s-master ~]# mkdir /etc/kubernetes
[root@k8s-master ~]# cd /etc/kubernetes
[root@k8s-master kubernetes]# scp -rp root@10.0.0.14:/opt/certs/capem .
[root@k8s-master kubernetes]# scp -rp root@10.0.0.14:/opt/certs/apiserverpem .
[root@k8s-master kubernetes]# scp -rp root@10.0.0.14:/opt/certs/client*pem .
[root@k8s-master kubernetes]# ls
apiserver-key.pem apiserver.pem ca-key.pem ca.pem client-key.pem client.pem
#api-server审计日志规则
[root@k8s-master kubernetes]# vi audit.yaml
iapiVersion: audit.k8s.io/v1beta1 # This is required.
kind: Policy
Don’t generate audit events for all requests in RequestReceived stage.
omitStages:
- “RequestReceived”
rules:
Log pod changes at RequestResponse level
- level: RequestResponse
resources:
Log “pods/log”, “pods/status” at Metadata level
- level: Metadata
resources:- group: “”
resources: [“pods/log”, “pods/status”]
- group: “”
Don’t log requests to a configmap called “controller-leader”
Don’t log watch requests by the “system:kube-proxy” on endpoints or services
- level: None
users: [“system:kube-proxy”]
verbs: [“watch”]
resources:- group: “” # core API group
resources: [“endpoints”, “services”]
- group: “” # core API group
Don’t log authenticated requests to certain non-resource URL paths.
- level: None
userGroups: [“system:authenticated”]
nonResourceURLs:- “/api*” # Wildcard matching.
- “/version”
Log the request body of configmap changes in kube-system.
- level: Request
resources:- group: “” # core API group
resources: [“configmaps”]
This rule only applies to resources in the “kube-system” namespace.
The empty string “” can be used to select non-namespaced resources.
namespaces: [“kube-system”] - group: “” # core API group
Log configmap and secret changes in all other namespaces at the Metadata level.
Log all other resources in core and extensions at the Request level.
- level: Request
resources:- group: “” # core API group
- group: “extensions” # Version of group should NOT be included.
A catch-all rule to log all other requests at the Metadata level.
-
level: Metadata
Long-running requests like watches that fall under this rule will not
generate an audit event in RequestReceived.
omitStages:
- “RequestReceived”
vi /usr/lib/systemd/system/kube-apiserver.service
i[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
After=etcd.service
[Service]
ExecStart=/usr/sbin/kube-apiserver
–audit-log-path /var/log/kubernetes/audit-log
–audit-policy-file /etc/kubernetes/audit.yaml
–authorization-mode RBAC
–client-ca-file /etc/kubernetes/ca.pem
–requestheader-client-ca-file /etc/kubernetes/ca.pem
–enable-admission-plugins NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota
–etcd-cafile /etc/kubernetes/ca.pem
–etcd-certfile /etc/kubernetes/client.pem
–etcd-keyfile /etc/kubernetes/client-key.pem
–etcd-servers https://10.0.0.11:2379,https://10.0.0.12:2379,https://10.0.0.13:2379
–service-account-key-file /etc/kubernetes/ca-key.pem
–service-cluster-ip-range 10.254.0.0/16
–service-node-port-range 30000-59999
–kubelet-client-certificate /etc/kubernetes/client.pem
–kubelet-client-key /etc/kubernetes/client-key.pem
–log-dir /var/log/kubernetes/
–logtostderr=false
–tls-cert-file /etc/kubernetes/apiserver.pem
–tls-private-key-file /etc/kubernetes/apiserver-key.pem
–v 2 #(日志级别)
Restart=on-failure
[Install]
WantedBy=multi-user.target #(安装到多个用户级别)
[root@k8s-master kubernetes]# mkdir /var/log/kubernetes
[root@k8s-master kubernetes]# systemctl daemon-reload
[root@k8s-master kubernetes]# systemctl start kube-apiserver.service
[root@k8s-master kubernetes]# systemctl enable kube-apiserver.service
#检验
[root@k8s-master kubernetes]# kubectl get cs
安装controller-manager服务
[root@k8s-master kubernetes]# vi /usr/lib/systemd/system/kube-controller-manager.service
i[Unit]
Description=Kubernetes Controller Manager
Documentation=https://github.com/kubernetes/kubernetes
After=kube-apiserver.service
[Service]
ExecStart=/usr/sbin/kube-controller-manager
–cluster-cidr 172.18.0.0/16 \ #(pod节点的网段)
–log-dir /var/log/kubernetes/
–master http://127.0.0.1:8080
–service-account-private-key-file /etc/kubernetes/ca-key.pem
–service-cluster-ip-range 10.254.0.0/16 \ #(vip 的网段)
–root-ca-file /etc/kubernetes/ca.pem
–logtostderr=false
–v 2
Restart=on-failure
[Install]
WantedBy=multi-user.target
[root@k8s-master kubernetes]# systemctl daemon-reload
[root@k8s-master kubernetes]# systemctl start kube-controller-manager.service
[root@k8s-master kubernetes]# systemctl enable kube-controller-manager.service
安装scheduler服务
[root@k8s-master kubernetes]# vi /usr/lib/systemd/system/kube-scheduler.service
i[Unit]
Description=Kubernetes Scheduler
Documentation=https://github.com/kubernetes/kubernetes
After=kube-apiserver.service
[Service]
ExecStart=/usr/sbin/kube-scheduler
–log-dir /var/log/kubernetes/
–master http://127.0.0.1:8080
–logtostderr=false
–v 2
Restart=on-failure
[Install]
WantedBy=multi-user.target
[root@k8s-master kubernetes]# systemctl daemon-reload
[root@k8s-master kubernetes]# systemctl start kube-scheduler.service
[root@k8s-master kubernetes]# systemctl enable kube-scheduler.service
验证master节点
[root@k8s-master kubernetes]# kubectl get cs
1.3.4 node节点的安装
安装kubelet服务
在node3节点上签发证书
[root@k8s-node3 bin]# cd /opt/certs/
[root@k8s-node3 certs]# vi kubelet-csr.json
i{
“CN”: “kubelet-node”,
“hosts”: [
“127.0.0.1”,
“10.0.0.11”,
“10.0.0.12”,
“10.0.0.13”,
“10.0.0.14”,
“10.0.0.15”
],
“key”: {
“algo”: “rsa”,
“size”: 2048
},
“names”: [
{
“C”: “CN”,
“ST”: “beijing”,
“L”: “beijing”,
“O”: “od”,
“OU”: “ops”
}
]
}
[root@k8s-node3 certs]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server kubelet-csr.json | cfssl-json -bare kubelet
[root@k8s-node3 certs]# ls kubelet*
kubelet.csr kubelet-csr.json kubelet-key.pem kubelet.pem
#生成kubelet启动所需的kube-config文件
[root@k8s-node3 certs]# ln -s /opt/softs/kubernetes/server/bin/kubectl /usr/sbin/
#设置集群参数
[root@k8s-node3 certs]# kubectl config set-cluster myk8s
–certificate-authority=/opt/certs/ca.pem
–embed-certs=true
–server=https://10.0.0.11:6443
–kubeconfig=kubelet.kubeconfig
#设置客户端认证参数
[root@k8s-node3 certs]# kubectl config set-credentials k8s-node --client-certificate=/opt/certs/client.pem --client-key=/opt/certs/client-key.pem --embed-certs=true --kubeconfig=kubelet.kubeconfig
#生成上下文参数
[root@k8s-node3 certs]# kubectl config set-context myk8s-context
–cluster=myk8s
–user=k8s-node
–kubeconfig=kubelet.kubeconfig
#切换默认上下文
[root@k8s-node3 certs]# kubectl config use-context myk8s-context --kubeconfig=kubelet.kubeconfig
#查看生成的kube-config文件
[root@k8s-node3 certs]# ls kubelet.kubeconfig
kubelet.kubeconfig
master节点上
[root@k8s-master ~]# vi k8s-node.yaml
iapiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding #(集群角色绑定)
Metadata:
name: k8s-node
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:node
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: k8s-node
[root@k8s-master ~]# kubectl create -f k8s-node.yaml
node1节点:
#安装docker-ce
[root@k8s-node1 ~]# wget http://192.168.15.253/docker1903_rpm.tar.gz
[root@k8s-node1 ~]# tar xf docker1903_rpm.tar.gz
[root@k8s-node1 ~]# cd docker1903_rpm/
[root@k8s-node1 docker1903_rpm]# yum -y localinstall *.rpm
[root@k8s-node1 docker1903_rpm]# systemctl start docker.service
[root@k8s-node1 docker1903_rpm]# systemctl enable docker.service
vim /etc/docker/daemon.json
i{
“registry-mirrors”: [“https://registry.docker-cn.com”],
“exec-opts”: [“native.cgroupdriver=systemd”]
}
systemctl restart docker.service
systemctl enable docker.service
[root@k8s-node1 ~]# mkdir /etc/kubernetes
[root@k8s-node1 ~]# cd /etc/kubernetes
[root@k8s-node1 kubernetes]# scp -rp root@10.0.0.14:/opt/certs/kubelet.kubeconfig .
[root@k8s-node1 kubernetes]# scp -rp root@10.0.0.14:/opt/certs/capem .
[root@k8s-node1 kubernetes]# scp -rp root@10.0.0.14:/opt/certs/kubeletpem .
[root@k8s-node1 kubernetes]# scp -rp root@10.0.0.14:/opt/softs/kubernetes/server/bin/kubelet /usr/bin/
[root@k8s-node1 kubernetes]# mkdir /var/log/kubernetes
[root@k8s-node1 kubernetes]# vi /usr/lib/systemd/system/kubelet.service
i[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service
[Service]
ExecStart=/usr/bin/kubelet
–anonymous-auth=false
–cgroup-driver systemd
–cluster-dns 10.254.230.254
–cluster-domain cluster.local
–runtime-cgroups=/systemd/system.slice
–kubelet-cgroups=/systemd/system.slice
–fail-swap-on=false
–client-ca-file /etc/kubernetes/ca.pem
–tls-cert-file /etc/kubernetes/kubelet.pem
–tls-private-key-file /etc/kubernetes/kubelet-key.pem
–hostname-override 10.0.0.12
–image-gc-high-threshold 20
–image-gc-low-threshold 10
–kubeconfig /etc/kubernetes/kubelet.kubeconfig
–log-dir /var/log/kubernetes/
–pod-infra-container-image t29617342/pause-amd64:3.0
–logtostderr=false
–v=2
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
注释: --fail-swap-on=false \ #(默认值是true,kubelate在启动的时候默认不支持swap,有swap的时候默认是有缓存的,)
–image-gc-high-threshold 20
–image-gc-low-threshold 10 \ #做镜像回收
–pod-infra-container-image t29617342/pause-amd64:3.0 \ #基础pod镜像容器地址
[root@k8s-node1 kubernetes]# systemctl daemon-reload
[root@k8s-node1 kubernetes]# systemctl start kubelet.service
[root@k8s-node1 kubernetes]# systemctl enable kubelet.service
node2节点:
以上步骤同node1节点只需改配置文件
[root@k8s-node2 kubernetes]# vi /usr/lib/systemd/system/kubelet.service
i[Unit]
Description=Kubernetes Kubelet
After=docker.service
Requires=docker.service
[Service]
ExecStart=/usr/bin/kubelet
–anonymous-auth=false
–cgroup-driver systemd
–cluster-dns 10.254.230.254
–cluster-domain cluster.local
–runtime-cgroups=/systemd/system.slice
–kubelet-cgroups=/systemd/system.slice
–fail-swap-on=false
–client-ca-file /etc/kubernetes/ca.pem
–tls-cert-file /etc/kubernetes/kubelet.pem
–tls-private-key-file /etc/kubernetes/kubelet-key.pem
–hostname-override 10.0.0.13
–image-gc-high-threshold 20
–image-gc-low-threshold 10
–kubeconfig /etc/kubernetes/kubelet.kubeconfig
–log-dir /var/log/kubernetes/
–pod-infra-container-image t29617342/pause-amd64:3.0
–logtostderr=false
–v=2
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
[root@k8s-node1 kubernetes]# systemctl daemon-reload
[root@k8s-node1 kubernetes]# systemctl start kubelet.service
[root@k8s-node1 kubernetes]# systemctl enable kubelet.service
master节点验证
[root@k8s-master ~]# kubectl get nodes
安装kube-proxy服务
在node3节点上签发证书
[root@k8s-node3 ~]# cd /opt/certs/
[root@k8s-node3 certs]# vi /opt/certs/kube-proxy-csr.json
i{
“CN”: “system:kube-proxy”,
“key”: {
“algo”: “rsa”,
“size”: 2048
},
“names”: [
{
“C”: “CN”,
“ST”: “beijing”,
“L”: “beijing”,
“O”: “od”,
“OU”: “ops”
}
]
}
[root@k8s-node3 certs]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client kube-proxy-csr.json | cfssl-json -bare kube-proxy-client
[root@k8s-node3 certs]# ls kube-proxy-c*
kube-proxy-client.csr kube-proxy-client-key.pem kube-proxy-client.pem kube-proxy-csr.json
#生成kube-proxy启动所需要kube-config
[root@k8s-node3 certs]# kubectl config set-cluster myk8s
–certificate-authority=/opt/certs/ca.pem
–embed-certs=true
–server=https://10.0.0.11:6443
–kubeconfig=kube-proxy.kubeconfig
[root@k8s-node3 certs]# kubectl config set-credentials kube-proxy
–client-certificate=/opt/certs/kube-proxy-client.pem
–client-key=/opt/certs/kube-proxy-client-key.pem
–embed-certs=true
–kubeconfig=kube-proxy.kubeconfig
[root@k8s-node3 certs]# kubectl config set-context myk8s-context
–cluster=myk8s
–user=kube-proxy
–kubeconfig=kube-proxy.kubeconfig
[root@k8s-node3 certs]# kubectl config use-context myk8s-context --kubeconfig=kube-proxy.kubeconfig
[root@k8s-node3 certs]# ls kube-proxy.kubeconfig
kube-proxy.kubeconfig
[root@k8s-node3 certs]# scp -rp kube-proxy.kubeconfig root@10.0.0.12:/etc/kubernetes/
[root@k8s-node3 certs]# scp -rp kube-proxy.kubeconfig root@10.0.0.13:/etc/kubernetes/
[root@k8s-node3 certs]# cd /opt/softs/kubernetes/server/bin/
[root@k8s-node3 bin]# scp -rp kube-proxy root@10.0.0.12:/usr/bin/
[root@k8s-node3 bin]# scp -rp kube-proxy root@10.0.0.13:/usr/bin/
在node1节点上配置kube-proxy
[root@k8s-node1 ~]# vi /usr/lib/systemd/system/kube-proxy.service
i[Unit]
Description=Kubernetes Proxy
After=network.target
[Service]
ExecStart=/usr/bin/kube-proxy
–kubeconfig /etc/kubernetes/kube-proxy.kubeconfig
–cluster-cidr 172.18.0.0/16
–hostname-override 10.0.0.12
–logtostderr=false
–v=2
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
[root@k8s-node1 ~]# systemctl daemon-reload
[root@k8s-node1 ~]# systemctl start kube-proxy.service
[root@k8s-node1 ~]# systemctl enable kube-proxy.service
Node2 节点上配置:
和node1一样,node2的/usr/lib/systemd/system/kube-proxy.service配置文件修改
–hostname-override 10.0.0.13
验证;
1.3.5 配置flannel网络
所有节点安装flannel(11、12、13)
yum install flannel -y
mkdir /opt/certs/
在node3上分发证书
[root@k8s-node3 ~]# cd /opt/certs/
[root@k8s-node3 certs]# scp -rp ca.pem clientpem root@10.0.0.11:/opt/certs/
[root@k8s-node3 certs]# scp -rp ca.pem clientpem root@10.0.0.12:/opt/certs/
[root@k8s-node3 certs]# scp -rp ca.pem client*pem root@10.0.0.13:/opt/certs/
在master节点上
etcd创建flannel的key
#通过这个key定义pod的ip地址范围
etcdctl mk /atomic.io/network/config ‘{ “Network”: “172.18.0.0/16”,“Backend”: {“Type”: “vxlan”} }’
#注意可能会失败提示
Error: x509: certificate signed by unkNown authority
#多重试几次就好了
配置启动flannel
vi /etc/sysconfig/flanneld
第4行:FLANNEL_ETCD_ENDPOINTS=“https://10.0.0.11:2379,https://10.0.0.12:2379,https://10.0.0.13:2379”
第8行不变:FLANNEL_ETCD_PREFIX="/atomic.io/network"
第11行:FLANNEL_OPTIONS="-etcd-cafile=/opt/certs/ca.pem -etcd-certfile=/opt/certs/client.pem -etcd-keyfile=/opt/certs/client-key.pem"
systemctl start flanneld.service
systemctl enable flanneld.service
[root@k8s-master ~]# scp -rp /etc/sysconfig/flanneld root@10.0.0.12:/etc/sysconfig/flanneld
[root@k8s-master ~]# scp -rp /etc/sysconfig/flannel root@10.0.0.13:/etc/sysconfig/flanneld
#验证
[root@k8s-master ~]# ifconfig flannel.1
flannel.1: flags=4163<UP,broADCAST,RUNNING,MULTICAST> mtu 1450
inet 172.18.43.0 netmask 255.255.255.255 broadcast 0.0.0.0
inet6 fe80::30d9:50ff:fe47:599e prefixlen 64 scopeid 0x20
ether 32:d9:50:47:59:9e txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 8 overruns 0 carrier 0 collisions 0
在node1和node2上
[root@k8s-node1 ~]# vim /usr/lib/systemd/system/docker.service
将ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
修改为ExecStart=/usr/bin/dockerd $DOCKER_NETWORK_OPTIONS -H fd:// --containerd=/run/containerd/containerd.sock
增加一行ExecStartPost=/usr/sbin/iptables -P FORWARD ACCEPT
[root@k8s-node1 ~]# systemctl daemon-reload
[root@k8s-node1 ~]# systemctl restart docker
验证:启动一个容器,测试网络通不通
Node1节点、node2节点启动一个容器
[root@k8s-node1 ~]# wget http://192.168.15.253/docker_images/docker_alpine3.9.tar.gz
[root@k8s-node1 ~]# docker load -i docker_alpine3.9.tar.gz
[root@k8s-node1 ~]# docker run -it alpine:3.9
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:12:4D:02
inet addr:172.18.77.2 Bcast:172.18.77.255 Mask:255.255.255.0
UP broADCAST RUNNING MULTICAST MTU:1450 Metric:1
RX packets:11 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:962 (962.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ #
[root@k8s-node2 ~]# wget http://192.168.15.253/docker_images/docker_alpine3.9.tar.gz
[root@k8s-node2 ~]# docker load -i docker_alpine3.9.tar.gz
[root@k8s-node2 ~]# docker run -it alpine:3.9
/ # ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:12:48:02
inet addr:172.18.72.2 Bcast:172.18.72.255 Mask:255.255.255.0
UP broADCAST RUNNING MULTICAST MTU:1450 Metric:1
RX packets:11 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:962 (962.0 B) TX bytes:0 (0.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
/ #
在master节点上测试网络:
[root@k8s-master ~]# ping 172.18.77.2
PING 172.18.77.2 (172.18.77.2) 56(84) bytes of data.
64 bytes from 172.18.77.2: icmp_seq=1 ttl=63 time=1.73 ms
^C
— 172.18.77.2 ping statistics —
1 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.367/1.049/1.732/0.683 ms
[root@k8s-master ~]# ping 172.18.72.2
PING 172.18.72.2 (172.18.72.2) 56(84) bytes of data.
64 bytes from 172.18.72.2: icmp_seq=1 ttl=63 time=2.57 ms
^C
— 172.18.72.2 ping statistics —
1 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.387/1.480/2.573/1.093 ms
#验证,docker0网络为172.18网段就ok了
[root@k8s-node1 ~]# ifconfig docker0
docker0: flags=4099<UP,broADCAST,MULTICAST> mtu 1500
inet 172.18.41.1 netmask 255.255.255.0 broadcast 172.18.41.255
ether 02:42:07:3e:8a:09 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
验证k8s集群的安装
[root@k8s-master ~]# kubectl run Nginx --image=Nginx:1.13 --replicas=2
#多等待一段时间,再查看pod状态
[root@k8s-master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READInesS GATES
Nginx-6459cd46fd-8lln4 1/1 Running 0 3m27s 172.18.41.2 10.0.0.12
Nginx-6459cd46fd-xxt24 1/1 Running 0 3m27s 172.18.96.2 10.0.0.13
[root@k8s-master ~]# kubectl expose deployment Nginx --port=80 --target-port=80 --type=NodePort
[root@k8s-master ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.254.0.1 443/TCP 6h46m
Nginx NodePort 10.254.160.83 80:41760/TCP 3s
#打开浏览器访问http://10.0.0.12:41760,能访问就ok了
1.4 修改IP地址、主机名和host解析
10.0.0.11 k8s-master
10.0.0.12 k8s-node-1
10.0.0.13 k8s-node-2
所有节点需要做hosts解析
1.5 master节点安装etcd
yum install etcd -y
vim /etc/etcd/etcd.conf
6行:ETCD_LISTEN_CLIENT_URLS=“http://0.0.0.0:2379”
21行:ETCD_ADVERTISE_CLIENT_URLS=“http://10.0.0.11:2379”
systemctl start etcd.service
systemctl enable etcd.service
etcdctl set testdir/testkey0 0
etcdctl get testdir/testkey0
etcdctl -C http://10.0.0.11:2379 cluster-health
etcd原生支持做集群,
etcd通过http协议启动
1.6 master节点安装kubernetes
yum install kubernetes-master.x86_64 -y
vim /etc/kubernetes/apiserver
8行: KUBE_API_ADDRESS="–insecure-bind-address=0.0.0.0"
11行:KUBE_API_PORT="–port=8080"
14行: KUBELET_PORT="–kubelet-port=10250"
17行:KUBE_ETCD_SERVERS="–etcd-servers=http://10.0.0.11:2379"
23行:KUBE_ADMISSION_CONTROL="–admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"
vim /etc/kubernetes/config
22行:KUBE_MASTER="–master=http://10.0.0.11:8080"
systemctl enable kube-apiserver.service
systemctl restart kube-apiserver.service
systemctl enable kube-controller-manager.service
systemctl restart kube-controller-manager.service
systemctl enable kube-scheduler.service
systemctl restart kube-scheduler.service
检查服务是否安装正常
[root@k8s-master ~]# kubectl get componentstatus
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
controller-manager Healthy ok
etcd-0 Healthy {“health”:“true”}
[k8s日志级别]
1.7 node节点安装kubernetes
yum install kubernetes-node.x86_64 -y
vim /etc/kubernetes/config
22行:KUBE_MASTER="–master=http://10.0.0.11:8080"
vim /etc/kubernetes/kubelet[注意:node节点的IP]
5行:KUBELET_ADDRESS="–address=0.0.0.0"
8行:KUBELET_PORT="–port=10250"
11行:KUBELET_HOSTNAME="–hostname-override=10.0.0.12"
14行:KUBELET_API_SERVER="–api-servers=http://10.0.0.11:8080"
systemctl enable kubelet.service
systemctl restart kubelet.service
systemctl enable kube-proxy.service
systemctl restart kube-proxy.service
在master节点检查
[root@k8s-master ~]# kubectl get nodes
NAME STATUS AGE
10.0.0.12 Ready 6m
10.0.0.13 Ready 3s
1.8 所有节点配置flannel网络
Flannel网络的特点:所有容器组合在一起,形成一个超大的局域网
Flannel三种模式:
Udp 模式:性能较差,配置最简单
Vxlan模式:性能比较好,
Host-gw:性能最好 云主机
#所有节点:
yum install flannel -y
sed -i ‘s#http://127.0.0.1:2379#http://10.0.0.11:2379#g’ /etc/sysconfig/flanneld
##master节点:
etcdctl mk /atomic.io/network/config ‘{ “Network”: “172.18.0.0/16”,“Backend”: {“Type”: “vxlan”} }’
[注意:复制的时候有没有特殊符号,有特殊符号的话,启动会报错]
为何不用172.17网段?
至少16位子网掩码,
systemctl enable flanneld.service
systemctl restart flanneld.service
##node节点:
systemctl enable flanneld.service
systemctl restart flanneld.service
systemctl restart docker (没有重启docker的话,docker和flannel不在同一网段)
systemctl restart kubelet.service
systemctl restart kube-proxy.service
Systemd的配置
Nginx
ExecStartPre=Nginx -t
ExecStart=Nginx 启动之前
ExecStartPost 启动之后
vim /usr/lib/systemd/system/docker.service
#在[Service]区域下增加一行
ExecStartPost=/usr/sbin/iptables -P FORWARD ACCEPT
systemctl daemon-reload
systemctl restart docker
1.9 配置master为镜像仓库
为什么要有一个私有仓库?
最快的速度启动容器
为了安全性,
#master节点
yum install docker -y
若安装失败:
yum clean all
vi /etc/docker/daemon.json
{
“registry-mirrors”: [“https://registry.docker-cn.com”],
“insecure-registries”: [“10.0.0.11:5000”]
}
systemctl enable docker
systemctl start docker
docker run -d -p 5000:5000 --restart=always --name registry -v /opt/myregistry:/var/lib/registry registry
#node节点
vi /etc/docker/daemon.json
{
“registry-mirrors”: [“https://registry.docker-cn.com”],
“insecure-registries”: [“10.0.0.11:5000”]
}
systemctl restart docker
2. 什么是k8s,k8s有什么功能?
k8s是一个docker集群的管理工具 ,[官方文档:kubernetes.io]
k8s是容器的编排工具,可以实现批量管理容器
2.1 k8s的核心功能
自愈: 重新启动失败的容器,在节点不可用时,替换和重新调度节点上的容器,对用户定义的健康检查不响应的容器会被中止,并且在容器准备好服务之前不会把其向客户端广播。[自我修复]
弹性伸缩: 通过监控容器的cpu的负载值,如果这个平均高于80%,增加容器的数量,如果这个平均低于10%,减少容器的数量
服务的自动发现和负载均衡: 不需要修改您的应用程序来使用不熟悉的服务发现机制,Kubernetes 为容器提供了自己的 IP 地址和一组容器的单个 DNS 名称,并可以在它们之间进行负载均衡。
滚动升级和一键回滚: Kubernetes 逐渐部署对应用程序或其配置的更改,同时监视应用程序运行状况,以确保它不会同时终止所有实例。 如果出现问题,Kubernetes会为您恢复更改,利用日益增长的部署解决方案的生态系统。
私密配置文件管理: web容器里面,数据库的账户密码(测试库密码)
2.2 k8s的历史
2013年 docker开源,容器
2014年 docker容器编排工具,立项,谷歌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
2.3 k8s的应用场景
k8s最适合跑微服务项目!
微服务:软件开发架构,微小的服务,[多套架构]
每个公司有一个独立的域名,拆了多少个功能就有多少个集群,
消息队列实现数据库的回滚功能,eg:RabbitMQ、kafka、redis、
微服务的好处:1)支持更高的并发
2)业务更加的健壮
3)更新迭代更快
mvc架构:(model viewer controller)[一套架构]
数据库:事务
K8s更适合微服务,为什么?
MVC维护一套集群,微服务维护上百套集群
开发环境:微服务,测试环境:微服务,预生产环境:微服务,生产环境:微服务
Docker镜像,快速部署,
K8s弹性伸缩:(容器不够加,多了减)
2.4 k8s的安装方式
yum安装 1.5 最容易安装成功,最适合学习的
源码编译安装—难度最大 可以安装最新版(go语言安装的,不推荐)
二进制安装—步骤繁琐 可以安装最新版 shell,ansible,saltstack(官方已经编辑好二进制包,只需要配置[但是配置繁琐],)[生产中最适合使用]
kubeadm 安装最容易, 网络(早期集群所需的镜像,必须访问谷歌的镜像仓库 ,) 可以安装最新版(容易使用) [生产中最适合使用]
minikube 适合开发人员体验k8s, 网络(仅限于单机)
3. k8s常用的资源
3.1 创建pod资源
创建pod流程:
yaml文件 kubectl create -f .
api-server 写入到etcd
api-server 调用scheduler
api-server调用kubeletpod配置文件
删除pod流程:
kubectl delete pod Nginx
api-server修改etcd中改pod的状态
api-server调用kubelet 停止并删除容器
api-server 删除etcd的pod记录
pod是最小资源单位.[pod是用来启动容器]
任何的一个k8s资源都可以由yml清单文件来定义[任何资源都可以用yml文件创建]
k8s yaml的主要组成[yml文件注意缩进]
apiVersion: v1 api版本
kind: pod 资源类型
Metadata: 属性
spec: 详细
步骤:(使用低版本的Nginx镜像,是方便后面的滚动升级)
Master节点:
⑴ #下载Nginx镜像
wget http://192.168.15.253/docker_images/docker_Nginx1.13.tar.gz
⑵ #导入Nginx镜像
docker load -i docker_Nginx1.13.tar.gz
⑶ #给Nginx镜像打标签
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
⑸ 创建pod资源
#创建目录
mkdir k8s_yaml
cd k8s_yaml
mkdir pod
cd pod
vim k8s_pod.yml
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
kubectl create -f k8s_pod.yml
#创建pod类型的资源
kubectl get pod
注意:pod资源名字不能相同
#查看pod类型的资源的状态
kubectl describe pod Nginx
51m 51m 1 {default-scheduler } normal Scheduled Successfully assigned Nginx to 10.0.0.13
51m 45m 6 {kubelet 10.0.0.13} Warning FailedSync Error syncing pod, skipping: Failed to “StartContainer” for “POD” with ErrImagePull: “image pull Failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request. details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)”
51m 43m 33 {kubelet 10.0.0.13} Warning FailedSync Error syncing pod, skipping: Failed to “StartContainer” for “POD” with ImagePullBackOff: “Back-off pulling image “registry.access.redhat.com/rhel7/pod-infrastructure:latest””
报错:
解决方法:解决软链接失效的问题,修改仓库为私有镜像
#node节点:
vim /etc/kubernetes/kubelet
KUBELET_POD_INFRA_CONTAINER="–pod-infra-container-image=10.0.0.11:5000/pod-infrastructure:latest"
systemctl restart kubelet.service
pod资源:至少由两个容器组成,pod基础容器和业务容器组成(最多1+4)
pod逻辑单元
创建一个pod资源,启动了两个容器(一个基础容器pod,一个业务容器Nginx+定制化操作)
K8s为什么要给业务容器绑定一个基础容器pod?
普通容器Nginx不能实现k8s的高级功能,把基础容器和业务容器捆绑在一块,看作是一个,共同实现k8s的高级功能
Pod资源至少有两个容器组成,一个基础容器pod,一个业务容器
pod配置文件2:
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”]
pod配置文件containers写了3个业务容器4个容器
k8s指定容器的初始命令args:
command :
dockerfile指定容器的初始命令CMD
ENTRYPOINT
imagePullPolicy:Always总是更新镜像Never从不更新
工fNotPresent如果本地没有,就去pull
spec:
containers:
image: 10.0.0.11:5000/wordpress :latestimagePullPolicy: Always
name : myweb
ports:
- containerPort: 80
nodeName: 10.0.0.13
3.2 ReplicationController资源
rc:保证指定数量的pod始终存活,rc通过标签选择器来关联pod(管理pod数量)
几个副本数,启动几个pod
k8s资源的常见操作:
kubectl create -f xxx.yaml
kubectl get pod|rc
kubectl describe pod Nginx
kubectl delete pod Nginx 或者kubectl delete -f xxx.yaml kubectl edit pod Nginx
创建一个rc
vi k8s_rc.yml
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
rc的滚动升级
新建一个Nginx-rc1.15.yaml
升级
kubectl rolling-update Nginx -f Nginx-rc1.15.yaml --update-period=10s
回滚
kubectl rolling-update Nginx2 -f Nginx-rc.yaml --update-period=1s
3.3 service资源(访问问题)
[创建service资源,自动分配vip,虚拟IP ping不通,虚拟IP,所有的cube-proxy上都有,一个pod死了,提出service资源]
提供负载均衡的资源,实现服务的自动发现和负载均衡,service的负载均衡是虚拟的,有虚拟的IP地址(cluster ip)[随机生成], service帮助pod暴露端口
创建一个service
apiVersion: v1
kind: Service #简称svc
Metadata:
name: myweb
spec:
type: NodePort #默认ClusterIP
ports:
- port: 80 #clusterIP
nodePort: 30000 #node port
targetPort: 80 #pod port
selector:
app: myweb2
#调整rc的副本书
kubectl scale rc Nginx --replicas=2
#进入pod容器
kubectl exec -it pod_name /bin/bash
修改nodePort范围
vim /etc/kubernetes/apiserver
KUBE_API_ARGS="–service-node-port-range=3000-50000"
命令行创建service资源(非交互式创建)
kubectl expose rc Nginx --type=NodePort --port=80
区别:命令行创建service,vip不能固定,宿主机端口都是随机分配的,
service默认使用iptables来实现负载均衡, k8s 1.8新版本中推荐使用lvs(四层负载均衡 传输层tcp,udp)
[iptables: 四表五链
{四表:
filter(实现数据包的过滤,把不安全的数据包拦截,)
nat(数据包地址转换)
raw(追踪,Linux追踪命令:traceroute Nginx.org #追踪Nginx.org)
mangle(数据包修改,数据包经过一个路由,-1,最后减完数据包丢弃,mangle负责修复这些数据);
五链:
数据包–prerouting链(判断是否是找后面)(不走input就去forWord转发)—input(过滤)–内核(判断属于哪个进程)–对应进程收到–返回内核–output–postrouting
Input(进来的数据包应用此规则链中的规则)
Preprouting(对数据包作路由选择前应用此链中的规则)
Forword(转发数据包时应用此规则链中的规则)
Postrouting(对数据包作路由选择后应用此链中的规则)
output(外出的数据包应用此规则链中的规则)}]
3.4 deployment资源(rc滚动升级,标签选择器变了,svc关联不上,服务中断)
创建deployment流程
yaml文件kubectl create -f .
api-server写入到etcd
controller-manager创建rs
controller-manager申请创建pod
有rc在滚动升级之后,会造成服务访问中断,于是k8s引入了deployment资源
创建deployment
apiVersion: extensions/v1beta1
kind: Deployment
Metadata:
name: Nginx
spec:
replicas: 3
strategy:
rollingUpdate:
maxSurge: 1 #多启动几个容器
maxUnavailable: 1 #最大不可用的pod数量
type: RollingUpdate
minReadySeconds: 30 #升级间隔30秒,超过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
requests:
cpu: 100m
deployment升级和回滚
deployment滚动升级服务不中断
deployment不依赖配置文件
修改配置文件立即生效
命令行创建deployment
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
查看deployment所有历史版本
kubectl rollout history deployment Nginx
deployment回滚到上一个版本
kubectl rollout undo deployment Nginx
deployment回滚到指定版本
kubectl rollout undo deployment Nginx --to-revision=2
3.5 tomcat+MysqL练习
#node节点:
#下载MysqL和Tomcat镜像文件
[root@k8s-node02 ~]# wget http://192.168.15.253/docker_images/docker-MysqL-5.7.tar.gz
[root@k8s-node02 ~]# wget http://192.168.15.253/docker_images/tomcat-app-v2.tar.gz
#导入MysqL和Tomcat镜像
[root@k8s-node02 ~]# docker load -i docker-MysqL-5.7.tar.gz
[root@k8s-node02 ~]# docker load -i tomcat-app-v2.tar.gz
#打标签推送MysqL和Tomcat镜像到私有仓库
[root@k8s-node02 ~]# docker tag docker.io/kubeguide/tomcat-app:v2
[root@k8s-node02 ~]# docker tag docker.io/MysqL:5.7 10.0.0.11:5000/MysqL:5.7
[root@k8s-node02 ~]# docker push 10.0.0.11:5000/tomcat-app:v2
[root@k8s-node02 ~]# docker push 10.0.0.11:5000/MysqL:5.7
#master节点:
#查看镜像文件是否推送成功
[root@k8s-master k8s_yaml]# ls /opt/myregistry/docker/registry/v2/repositories/
alpine MysqL Nginx pod-infrastructure tomcat-app
#上传MysqL和Tomcat的yaml文件并解压
[root@k8s-master k8s_yaml]# ls
pod rc svc tomcat_demo.zip
[root@k8s-master k8s_yaml]# unzip tomcat_demo.zip
[root@k8s-master k8s_yaml]# ls
pod rc svc tomcat_demo tomcat_demo.zip
[root@k8s-master k8s_yaml]# cd tomcat_demo/
[root@k8s-master tomcat_demo]# rm -rf pv
[root@k8s-master tomcat_demo]# ls
MysqL-rc.yml MysqL-svc.yml tomcat-rc.yml tomcat-svc.yml
[root@k8s-master tomcat_demo]# kubectl create -f MysqL-rc.yml
[root@k8s-master tomcat_demo]# kubectl create -f MysqL-svc.yml
[root@k8s-master tomcat_demo]# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 443/TCP 1d
MysqL 10.254.215.126 3306/TCP 9s
myweb 10.254.165.253 80:30000/TCP 5h
[root@k8s-master tomcat_demo]# vim tomcat-rc.yml
- name: MysqL_SERVICE_HOST
value: ‘10.254.215.126’
[root@k8s-master tomcat_demo]# kubectl create -f tomcat-rc.yml
[root@k8s-master tomcat_demo]# kubectl create -f tomcat-svc.yml
[root@k8s-master tomcat_demo]# kubectl get pod
NAME READY STATUS RESTARTS AGE
MysqL-m2qws 1/1 Running 0 2m
myweb-x2jl6 1/1 Running 0 1m
Nginx 1/1 Running 1 22h
Nginx2-j0xw7 1/1 Running 1 18h
Nginx2-m5jzg 1/1 Running 0 18h
Nginx2-w4gzl 1/1 Running 0 18h
test 2/2 Running 34 21h
在k8s中容器之间相互访问,通过VIP地址!
浏览器访问10.0.0.1:30008/demo
- k8s的常用资源(二进制)
4.1 k8s资源的常见操作:
kubectl get
kubectl create
kubectl delete
kubectl edit
kubectl describe
kubectl path “ixxx: {“xxx” :test;xcxc:[3}”
kubectl explain #查看帮助
4.2 pod资源
pod资源至少由两个容器组成,一个基础容器pod+业务容器
动态pod,这个pod的yaml文件从etcd获取的yaml
静态pod,kubelet本地目录读取yaml文件,启动的pod
mkdir /etc/kubernetes/manifest
vim /usr/lib/systemd/system/kubelet.service
#启动参数增加一行
–pod-manifest-path /etc/kubernetes/manifest \
systemctl daemon-reload
systemctl restart kubelet.service
cd /etc/kubernetes/manifest/
vi k8s_pod.yaml
iapiVersion: v1
kind: Pod
Metadata:
name: static-pod
spec:
containers:
- name: Nginx
image: Nginx:1.13
ports:
- containerPort: 80
#验证
[root@k8s-master ~]# kubectl get pod
4.3 污点和容忍度(二进制)
K8s里面为什么需要有污点和容忍度,它的适用范围是什么?
污点taints是定义在节点之上的键值型属性数据,用于让节点拒绝将Pod调度运行于其上, 除非该Pod对象具有接纳节点污点的容忍度。而容忍度tolerations是定义在 Pod对象上的键值型属性数据,用于配置其可容忍的节点污点,而且调度器仅能将Pod对象调度至其能够容忍该节点污点的节点之上,如图所示
节点选择器nodeselector和节点亲和性nodeAffinity两种调度方式都是通过在 Pod对象上添加标签选择器来完成对特定类型节点标签的匹配,它们实现的是由Pod选择节点的机制。而污点和容忍度则是通过向节点添加污点信息来控制Pod对象的调度结果,从而赋予了节点控制何种Pod对象能够调度于其上的主控权。简单来说,节点亲和性使得Pod对象被吸引到一类特定的节点,而污点则相反,它提供了让节点排斥特定Pod对象的能力。
Kubernetes使用PodToleratesNodeTaints预选策略和 TaintTolerationPriority优选函数来完成此种类型的高级调度机制。
污点: 给node节点加污点
污点是node节点的属性,通过打标签实现,[如何加标签?kubectl label nodes 10.0.0.12 node-role.kubernetes.io/node=;删除标签:kubectl label nodes 10.0.0.12 node-role.kubernetes.io/node-]
污点的类型:
NoSchedule:[不要再往该node节点调度,不会影响已有的pod]
PreferNoSchedule:[备用,尽量不要调度]
NoExecute:[清场,驱逐,]
kubectl scale deployment Nginx --replicas=n
打污点:kubectl taint node 10.0.0.12 disk=ssd: NoSchedule
取消污点:kubectl taint node 10.0.0.12 disk-
#添加污点的例子
kubectl taint node 10.0.0.14 node-role.kubernetes.io=master:NoExecute
#检查
[root@k8s-master ~]# kubectl describe nodes 10.0.0.14|grep -i taint
Taints: node-role.kubernetes.io=master:NoExecute
容忍度
#添加在pod的spec下
tolerations:
- key: “node-role.kubernetes.io” [#与标签相同]
operator: “Exists”
value: “master”
effect: “NoExecute”
4.4 secrets资源
[存储密码(bash64加密)和秘钥、ssh证书,]
方式1:
kubectl create secret docker-registry harbor-secret --namespace=default --docker-username=admin --docker-password=a123456 --docker-server=blog.oldqiang.com
vi k8s_sa_harbor.yaml
apiVersion: v1
kind: ServiceAccount
Metadata:
name: docker-image
namespace: default
imagePullSecrets:
- name: harbor-secret
vi k8s_pod.yaml
iapiVersion: v1
kind: Pod
Metadata:
name: static-pod
spec:
serviceAccount: docker-image
containers:
- name: Nginx
image: blog.oldqiang.com/oldboy/Nginx:1.13
ports:
- containerPort: 80
方法二(常用)
kubectl create secret docker-registry regcred --docker-server=blog.oldqiang.com --docker-username=admin --docker-password=a123456 --docker-email=296917342@qq.com
#验证
[root@k8s-master ~]# kubectl get secrets
NAME TYPE DATA AGE
default-token-vgc4l kubernetes.io/service-account-token 3 2d19h
regcred kubernetes.io/dockerconfigjson 1 114s
[root@k8s-master ~]# cat k8s_pod.yaml
apiVersion: v1
kind: Pod
Metadata:
name: static-pod
spec:
nodeName: 10.0.0.12
imagePullSecrets:
- name: regcred
containers:
- name: Nginx
image: blog.oldqiang.com/oldboy/Nginx:1.13
ports:
- containerPort: 80
[部署harbor:
wget–tar xf–证书秘钥–vim harbor.yml–域名+证书私钥路径+密码–安.装docker compose–执行./ install.sh–注意执行路径(harbor目录下)–over–登录
局部资源(同namespace)
配置了secret(加密密钥对)、不需要登录仓库就可以下拉镜像]
4.5 configmap资源
存放帮助挂载管理配置文件—此时出现了一个问题(挂载之后,原文件被隐藏)–使用一个资源解决该问题(initcontainer)
vi /opt/81.conf
server {
listen 81;
server_name localhost;
root /html;
index index.html index.htm;
location / {
}
}
kubectl create configmap 81.conf --from-file=/opt/81.conf
#验证
kubectl get cm
vi k8s_deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
Metadata:
name: Nginx
spec:
replicas: 2
template:
Metadata:
labels:
app: Nginx
spec:
volumes:
- name: Nginx-config
configMap:
name: 81.conf
items:
- key: 81.conf
path: 81.conf
containers:
- name: Nginx
image: Nginx:1.13
volumeMounts:
- name: Nginx-config
mountPath: /etc/Nginx/conf.d
ports:
- containerPort: 80
name: port1
- containerPort: 81
name: port2
4.6 initcontainter
kubernetes的初始化容器initcontains
initContainers是一种专用的容器,在应用程序容器启动之前运行,可以包括一些应用程序镜像中不存在的实用工具和安装脚本,可以完成应用的必要数据初始化等工作。总的来说就是在正式的容器启动之前做一些准备工作的。
例如一个应用容器挂载的volume目录需要一些必不可少的初始化文件,不加init容器的时候直接挂载volume应用容器的那个目录是空的(因为docker挂载一个volume时,会用volume的内容覆盖容器内挂载目录的内容),这就需要让init容器也跟应用容器挂载同一个volume目录,将初始化文件放进去,然后在启动应用容器就能正常看到那些初始化文件了,我也正是遇到了这样的问题,才来研究和学习init容器的。
1、一个pod可以运行多个容器,同样的一个pod也可能有一个或多个先于应用容器启动的 Init 容器,每个容器启动失败后都会根据你配置的重启策略进行重启,直到运行成功。Init 容器与普通的基本一样,主要区别如下:
• Init 容器总是运行到成功运行完为止。
• 前面的 Init 容器必须已经运行完成,才会开始运行下一个init容器,而应用程序容器时并行运行的。
2、因为 Init 容器具有与应用程序容器分离的单独镜像,所以使用他们可以具有如下优势:
• 它们可以包含并运行实用工具,但是出于安全考虑,是不建议在应用程序容器镜像中包含这些实用工具的。
• 它们可以包含使用工具和定制化代码来安装,但是不能出现在应用程序镜像中。例如,创建镜像没必要 FROM 另一个镜像,只需要在安装过程中使用类似 sed、 awk、 python 或 dig 这样的工具。
• 应用程序镜像可以分离出创建和部署的角色,而没有必要联合它们构建一个单独的镜像。
• Init 容器使用 Linux Namespace,所以相对应用程序容器来说具有不同的文件系统视图。因此,它们能够具有访问 Secret 的权限,而应用程序容器则不能。
• 它们必须在应用程序容器启动之前运行完成,而应用程序容器是并行运行的,所以 Init 容器能够提供了一种简单的阻塞或延迟应用容器的启动的方法,直到满足了一组先决条件。
3、下面是一些如何使用 Init 容器的思路:
• 等待一个 Service 创建完成,通过类似如下 shell 命令:
• for i in {1…100}; do sleep 1; if dig myservice; then exit 0; fi; exit 1
• 将 Pod 注册到远程服务器,通过在命令中调用 API,类似如下:
• curl -X POST http://
M
A
N
A
G
E
M
E
N
T
S
E
R
V
I
C
E
H
O
S
T
:
MANAGEMENT_SERVICE_HOST:
MANAGEMENTSERVICEHOST:MANAGEMENT_SERVICE_PORT/register -d ‘instance=KaTeX parse error: Expected 'EOF', got '&' at position 13: (<POD_NAME>)&̲ip=(<POD_IP>)’
• 在启动应用容器之前等一段时间,使用类似 sleep 60 的命令。
• 克隆 Git 仓库到数据卷。
• 将配置值放到配置文件中,运行模板工具为主应用容器动态地生成配置文件。例如,在配置文件中存放 POD_IP 值,并使用 Jinja 生成主应用配置文件。
4、 init容器使用示例,
Kubernetes 1.6 版本后使用新语法,把 Init 容器的声明移到 spec 中,只需要添加 initContainers 即可,下面列一个具有 2 个 Init 容器的简单 Pod。 第一个等待 myservice 启动,第二个等待 mydb 启动。 一旦这两个 Service 都启动完成,Pod 将开始启动。
apiVersion: v1
kind: Pod
Metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busyBox
command: [‘sh’, ‘-c’, ‘echo The app is running! && sleep 3600’]
initContainers: - name: init-myservice
image: busyBox
command: [‘sh’, ‘-c’, ‘until nslookup myservice; do echo waiting for myservice; sleep 2; done;’] - name: init-mydb
image: busyBox
command: [‘sh’, ‘-c’, ‘until nslookup mydb; do echo waiting for mydb; sleep 2; done;’]
下面的 yaml 文件展示了 mydb 和 myservice 两个 Service:
kind: Service
apiVersion: v1
Metadata:
name: myservice
spec:
ports:- protocol: TCP
port: 80
targetPort: 9376
- protocol: TCP
kind: Service
apiVersion: v1
Metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
这个 Pod 可以使用下面的命令进行启动和调试
$ kubectl create -f myapp.yaml
pod “myapp-pod” created
$ kubectl get -f myapp.yaml
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 6m
$ kubectl describe -f myapp.yaml
Name: myapp-pod
Namespace: default
[…]
Labels: app=myapp
Status: Pending
[…]
Init Containers:
init-myservice:
[…]
State: Running
[…]
init-mydb:
[…]
State: Waiting
Reason: PodInitializing
Ready: False
[…]
Containers:
myapp-container:
[…]
State: Waiting
Reason: PodInitializing
Ready: False
[…]
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
16s 16s 1 {default-scheduler } normal Scheduled Successfully assigned myapp-pod to 172.17.4.201
16s 16s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} normal Pulling pulling image “busyBox”
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} normal Pulled Successfully pulled image “busyBox”
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} normal Created Created container with docker id 5ced34a04634; Security:[seccomp=unconfined]
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} normal Started Started container with docker id 5ced34a04634
$ kubectl logs myapp-pod -c init-myservice # Inspect the first init container
$ kubectl logs myapp-pod -c init-mydb # Inspect the second init container
一旦我们启动了 mydb 和 myservice 这两个 Service,我们能够看到 Init 容器完成,并且 myapp-pod 被创建:
$ kubectl create -f services.yaml
service “myservice” created
service “mydb” created
$ kubectl get -f myapp.yaml
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 9m
在 Pod 上使用 activeDeadlineseconds,在容器上使用 livenessProbe,这样能够避免 Init 容器一直失败, 这就为 Init 容器活跃设置了一个期限。在 Pod 中的每个 app 和 Init 容器的名称必须唯一,与任何其它容器共享同一个名称,会在验证时抛出错误。
在 Pod 启动过程中,Init 容器会按顺序在网络和数据卷初始化之后启动。 每个容器必须在下一个容器启动之前成功退出。 如果由于运行时或失败退出,导致容器启动失败,它会根据 Pod 的 restartPolicy 指定的策略进行重试,在所有的 Init 容器没有成功之前,Pod 将不会变成 Ready 状态,如果 Pod 重启,所有 Init 容器必须重新执行。
因为 Init 容器可能会被重启、重试或者重新执行,所以 Init 容器的代码应该是幂等的(即任意多次执行所产生的影响与一次执行的影响相同)。 特别地,被写到 EmptyDirs 中文件的代码,应该对输出文件可能已经存在做好准备。
5、Pod 能够重启,会导致 Init 容器重新执行,重启主要有如下几个原因:
• 用户更新 PodSpec 导致 Init 容器镜像发生改变。更改 Init 容器的 image 字段,等价于重启该 Pod,应用容器镜像的变更只会重启应用容器。
• Pod 基础设施容器被重启。这不多见,但某些具有 root 权限可访问 Node 的人可能会这样做。
• 当 restartPolicy 设置为 Always,Pod 中所有容器会终止,强制重启,由于垃圾收集导致 Init 容器完成的记录丢失。
5. k8s常用服务(二进制)
5.1 部署dns服务
Dns服务的作用:将SVC的名字解析成clusterIP[k8s中]
RBAC:role base access controller [每启动一个RBAC,pod里就会有个用户]
role [局部角色role 、全剧角色clusterrole,]
(用户sa ServiceAccount
角色绑定:ClusterRoleBinding)
vi coredns.yaml
apiVersion: v1
kind: ServiceAccount
Metadata:
name: coredns
namespace: kube-system
labels:
kubernetes.io/cluster-service: “true”
addonmanager.kubernetes.io/mode: Reconcile
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
Metadata:
labels:
kubernetes.io/bootstrapping: rbac-defaults
addonmanager.kubernetes.io/mode: Reconcile
name: system:coredns
rules:
- apiGroups:
- “”
resources: - endpoints
- services
- pods
- namespaces
verbs: - list
- watch
- “”
- apiGroups:
- “”
resources: - nodes
verbs: - get
- “”
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
Metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: “true”
labels:
kubernetes.io/bootstrapping: rbac-defaults
addonmanager.kubernetes.io/mode: EnsureExists
name: system:coredns
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:coredns
subjects:
apiVersion: v1
kind: ConfigMap
Metadata:
name: coredns
namespace: kube-system
labels:
addonmanager.kubernetes.io/mode: EnsureExists
data:
Corefile: |
.:53 {
errors
health
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
upstream
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
—#普罗米修斯自带了export
apiVersion: apps/v1
kind: Deployment
Metadata:
name: coredns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: “true”
addonmanager.kubernetes.io/mode: Reconcile
kubernetes.io/name: “coredns”
spec:
replicas: not specified here:
strategy:#滚动升级策略
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
selector:
matchLabels:
k8s-app: kube-dns
template:#pod模板
Metadata:
labels:
k8s-app: kube-dns
annotations:
seccomp.security.alpha.kubernetes.io/pod: ‘docker/default’
spec:
priorityClassName: system-cluster-critical
serviceAccountName: coredns
tolerations:#容忍度
- key: “CriticalAddonsOnly”
operator: “Exists”
nodeselector:#适配标签
beta.kubernetes.io/os: linux
nodeName: 10.0.0.13
containers:
- name: coredns
image: coredns/coredns:1.3.1
imagePullPolicy: IfNotPresent #镜像策略:如果本地有就不去pull
resources:
limits:
memory: 100Mi
requests:#与调度有关
cpu: 100m
memory: 70Mi
args: [ “-conf”, “/etc/coredns/Corefile” ]#指定启动参数
volumeMounts:
- name: config-volume
mountPath: /etc/coredns
readOnly: true
- name: tmp
mountPath: /tmp
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
- containerPort: 9153
name: metrics
protocol: TCP
livenessProbe:#健康检查
httpGet:
path: /health
port: 8080
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successthreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /health
port: 8080
scheme: HTTP
securityContext:
allowPrivilegeEscalation: false
capabilities:
add:
- NET_BIND_SERVICE
drop:
- all
readOnlyRootFilesystem: true
dnsPolicy: Default
volumes:
- name: tmp
emptyDir: {}
- name: config-volume
configMap:
name: coredns
items:
- key: Corefile
path: Corefile
apiVersion: v1
kind: Service
Metadata:
name: kube-dns
namespace: kube-system
annotations:
prometheus.io/port: “9153”
prometheus.io/scrape: “true”
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: “true”
addonmanager.kubernetes.io/mode: Reconcile
kubernetes.io/name: “coredns”
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 - name: metrics
port: 9153
protocol: TCP
#测试
yum install bind-utils.x86_64 -y
dig @172.18.77.6 kubernetes.default.svc.cluster.local
dig @:指定dns
5.2 部署dashboard服务
认证,exec,增加一些资源类型
[root@k8s-node1 ~]# wget http://192.168.15.253/k8s-tools/docker_k8s_kubernetes-dashboard.tar.gz
[root@k8s-node1 ~]# docker load -i docker_k8s_kubernetes-dashboard.tar.gz
[root@k8s-master k8s_yaml]# cd dashboard/
[root@k8s-master dashboard]# vim dashboard.yaml
[root@k8s-master dashboard]# kubectl create -f dashboard.yaml
[root@k8s-master dashboard]# kubectl get pod -n kube-system
[root@k8s-master dashboard]# kubectl get svc -n kube-system
[root@k8s-master dashboard]# vim dashboard.yaml
[root@k8s-master dashboard]# kubectl get secrets -n kube-system
浏览器访问:https://10.0.0.12:30005
点击令牌登录,令牌号是token 码,
[root@k8s-master dashboard]# rm -rf rbac.yaml
[root@k8s-master dashboard]# kubectl get clusterrole|grep admin
admin 27h
cluster-admin 27h
system:aggregate-to-admin 27h
system:kubelet-api-admin 27h
[root@k8s-master dashboard]# vim dashboard-rbac.yaml
apiVersion: v1
kind: ServiceAccount
Metadata:
labels:
k8s-app: kubernetes-dashboard
addonmanager.kubernetes.io/mode: Reconcile
name: kubernets-admin
namespace: kube-system
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
Metadata:
name: kubernetes-dashboard-admin
namespace: kube-system
labels:
k8s-app: kubernetes-dashboard
addonmanager.kubernetes.io/mode: Reconcile
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: kubernets-admin
namespace: kube-system
[root@k8s-master dashboard]# kubectl create -f dashboard-rbac.yaml
[root@k8s-master dashboard]# kubectl describe secrets -n kube-system kubernets-admin-token-zqlzg
Name: kubernets-admin-token-zqlzg
Namespace: kube-system
Labels:
Annotations: kubernetes.io/service-account.name: kubernets-admin
kubernetes.io/service-account.uid: aa1107b0-86e0-4342-966a-5e41adbe866d
Type: kubernetes.io/service-account-token
Data
ca.crt: 1354 bytes
namespace: 11 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldHMtYWRtaW4tdG9rZW4tenFsemciLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoia3ViZXJuZXRzLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiYWExMTA3YjAtODZlMC00MzQyLTk2NmEtNWU0MWFkYmU4NjZkIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmt1YmVybmV0cy1hZG1pbiJ9.AottRsdjvkonJCECN6gNQtJR4xqmgwgu45-xQ2fZZzku-9TDsN2VQrG92dZB5t8AHcslpVyhTr2k65kDy6BcWHEoGHN-BHNe-fJqoj0KmWAnOOkoRtsVACEtrQwmXjwHcAblClA8Vrjl_HRJkYNBxeUVzoKsWJOSQeK2_ksQnt-qPzOXgl4kIs6UQfgNrx_O92ZMOwxYNHjO9meMplitacynVzgvW3QoU4JfdUABhg3YZwdhEcrfkeEQtEv_Kx2127NxKPErgY_wnt6lVgRvboVhzBrZObMxhT4DQtmmOSmTJz_ElgiHYpEJeouL9vFar12g-IqdL5E5pbYDlPZYQg
火狐浏览器访问:https:10.0.0.12:30005
有些功能火狐浏览器实现不了,用谷歌浏览器(需要做证书)
[root@k8s-master dashboard]# cd key/
[root@k8s-master key]# ls
dashboard.crt dashboard.csr dashboard.key
[root@k8s-master key]# kubectl delete secret kubernetes-dashboard-certs -n kube-system
[root@k8s-master key]# kubectl create secret generic kubernetes-dashboard-certs --from-file=dashboard.key --from-file=dashboard.crt -n kube-system
[root@k8s-master key]# kubectl get pod -n kube-system -o wide
[root@k8s-master key]# kubectl delete pod -n kube-system
[root@k8s-master key]# kubectl get pod -n kube-system -o wide
用谷歌浏览器登录https://10.0.0.12:30005
在这里我们记不住令牌,我们可以做一个文件,每次登陆用kubeconfig登录;
[root@k8s-master key]# kubectl describe secrets -n kube-system kubernets-admin-token-zqlzg
[root@k8s-master key]# DASH_TOCKEN=‘eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldHMtYWRtaW4tdG9rZW4tenFsemciLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoia3ViZXJuZXRzLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiYWExMTA3YjAtODZlMC00MzQyLTk2NmEtNWU0MWFkYmU4NjZkIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmt1YmVybmV0cy1hZG1pbiJ9.AottRsdjvkonJCECN6gNQtJR4xqmgwgu45-xQ2fZZzku-9TDsN2VQrG92dZB5t8AHcslpVyhTr2k65kDy6BcWHEoGHN-BHNe-fJqoj0KmWAnOOkoRtsVACEtrQwmXjwHcAblClA8Vrjl_HRJkYNBxeUVzoKsWJOSQeK2_ksQnt-qPzOXgl4kIs6UQfgNrx_O92ZMOwxYNHjO9meMplitacynVzgvW3QoU4JfdUABhg3YZwdhEcrfkeEQtEv_Kx2127NxKPErgY_wnt6lVgRvboVhzBrZObMxhT4DQtmmOSmTJz_ElgiHYpEJeouL9vFar12g-IqdL5E5pbYDlPZYQg’
[root@k8s-master key]# kubectl config set-context admin --cluster=kubernetes --user=admin --kubeconfig=/root/dashbord-admin.conf
[root@k8s-master key]# kubectl config use-context admin --kubeconfig=/root/dashbord-admin.conf
[root@k8s-master key]# kubectl config set-cluster kubernetes --server=10.0.0.11:6443 --kubeconfig=/root/dashbord-admin.conf
[root@k8s-master key]# kubectl config set-credentials admin --token=$DASH_TOCKEN --kubeconfig=/root/dashbord-admin.conf
[root@k8s-master key]# ls
dashboard.crt dashboard.csr dashboard.key
You have new mail in /var/spool/mail/root
[root@k8s-master key]# cd
[root@k8s-master ~]# ll
total 24
-rw-------. 1 root root 1522 Aug 28 11:27 anaconda-ks.cfg
-rw------- 1 root root 1134 Dec 15 16:15 dashbord-admin.conf
-rw-r–r-- 1 root root 259 Dec 14 15:06 k8s-node.yaml
drwxr-xr-x 10 root root 147 Dec 15 11:26 k8s_yaml
-rw-r–r-- 1 root root 9433 Dec 12 16:42 k8s_yaml.tar.gz
[root@k8s-master ~]# sz dashbord-admin.conf
- k8s的网络访问(二进制)
6.1 k8s的映射
endpoint和SVC是通过什么关联的?
endpoint和SVC都属于局部资源,必须写在同一个spacename里面,通过名字相同关联。
#准备数据库
Node2节点(10.0.0.13)
yum install mariadb-server -y
systemctl start mariadb
MysqL
MysqL>grant all on . to root@’%’ identified by ‘123456’;
master节点
#删除MysqL的rc和svc
kubectl delete rc MysqL
kubectl delete svc MysqL
#创建endpoint和svc
[root@k8s-master yingshe]# cat MysqL_endpoint.yaml
apiVersion: v1
kind: Endpoints
Metadata:
name: MysqL
subsets:
- addresses:
- ip: 10.0.0.13
ports: - name: MysqL
port: 3306
protocol: TCP
- ip: 10.0.0.13
[root@k8s-master yingshe]# cat MysqL_svc.yaml
apiVersion: v1
kind: Service
Metadata:
name: MysqL
spec:
ports:
- name: MysqL
port: 3306
protocol: TCP
targetPort: 3306
type: ClusterIP
#web页面重新访问tomcat/demo
#验证
[root@k8s-node2 ~]# MysqL -e ‘show databases;’
±-------------------+
| Database |
±-------------------+
| information_schema |
| HPE_APP |
| MysqL |
| performance_schema |
±-------------------+
6.2 kube-proxy的ipvs模式
node1节点:
yum install conntrack-tools -y
yum install ipvsadm.x86_64 -y
vim /usr/lib/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Proxy
After=network.target
[Service]
ExecStart=/usr/bin/kube-proxy
–kubeconfig /etc/kubernetes/kube-proxy.kubeconfig
–cluster-cidr 172.18.0.0/16
–hostname-override 10.0.0.12
–proxy-mode ipvs
–logtostderr=false
–v=2
Restart=on-failure
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl restart kube-proxy.service
ipvsadm -L -n
6.3 Ingress(访问权)
Service:实现四层负载均衡 lvs [不能配域名]
Ingress:实现七层负载均衡 Nginx[可以配域名]
原理:
启动kube-proxy服务,就会有一个vip,(在iptables规则中有)前提是node节点上安装kube-proxy服务,通过vip把用户的请求抛向后面的pod上,实现负载均衡由于这个是四层负载均衡,转发的次数较多,影响了用户的体验,为了提高用户体验,我们引出了ingress,然而Ingress是启动在容器里面的:ingress-controller(ingress控制器)
ingress控制器的实现方式:[pod 容器使用宿主机的网络]
haproxy
Nginx
traefik(公司中常用)
部署ingress-controller(使用Traefik)让容器使用宿主机的IP
Master节点;
[root@k8s-master ~]#cd k8s_yaml/
[root@k8s-master k8s_yaml]#vim k8s_test.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
Metadata:
name: Nginx-ds
labels:
addonmanager.kubernetes.io/mode: Reconcile
spec:
template:
Metadata:
labels:
app: Nginx-ds
spec:
hostNetwork: true
containers:
- name: my-Nginx
image: Nginx:1.13
ports:
- containerPort: 80
hostPort: 80
[root@k8s-master k8s_yaml]# kubectl create -f k8s_test.yaml
在node节点上查看:
[root@k8s-node1 ~]# netstat -ntplu
浏览器访问10.0.0.12
部署ingress:
ingress-traefik
Traefik 是一款开源的反向代理与负载均衡工具。它最大的优点是能够与常见的微服务系统直接整合,可以实现自动化动态配置。目前支持 Docker、Swarm、Mesos/Marathon、 Mesos、Kubernetes、Consul、Etcd、Zookeeper、BoltDB、Rest API 等等后端模型。
6.3.1 traefik实战
创建rbac
apiVersion: v1
kind: ServiceAccount
Metadata:
name: traefik-ingress-controller
namespace: kube-system
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
Metadata:
name: traefik-ingress-controller
rules:
- apiGroups:
- “”
resources: - services
- endpoints
- secrets
verbs: - get
- list
- watch
- “”
- apiGroups:
- extensions
resources: - ingresses
verbs: - get
- list
- watch
- extensions
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
Metadata:
name: traefik-ingress-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: traefik-ingress-controller
subjects:
- kind: ServiceAccount
name: traefik-ingress-controller
namespace: kube-system
直接在集群中创建即可:
$ kubectl create -f rbac.yaml
serviceaccount “traefik-ingress-controller” created
clusterrole.rbac.authorization.k8s.io “traefik-ingress-controller” created
clusterrolebinding.rbac.authorization.k8s.io “traefik-ingress-controller” created
部署traefik服务
Master节点:
[root@k8s-master k8s_yaml]# cd ingress/
[root@k8s-master ingress]# ls
ingress.yaml rabc.yaml traefik.yaml
[root@k8s-master ingress]# kubectl create -f rabc.yaml
[root@k8s-master ingress]# vim traefik.yaml
kind: DaemonSet
apiVersion: extensions/v1beta1
Metadata:
name: traefik-ingress-controller
namespace: kube-system
labels:
k8s-app: traefik-ingress-lb
spec:
selector:
matchLabels:
k8s-app: traefik-ingress-lb
template:
Metadata:
labels:
k8s-app: traefik-ingress-lb
name: traefik-ingress-lb
spec:
serviceAccountName: traefik-ingress-controller
terminationGracePeriodSeconds: 60
hostNetwork: true
containers:
- image: traefik:v1.7.2
imagePullPolicy: IfNotPresent
name: traefik-ingress-lb
ports:
- name: http
containerPort: 80
hostPort: 80
- name: admin
containerPort: 8080
hostPort: 8080
args:
- --api
- --kubernetes
- --logLevel=INFO
kind: Service
apiVersion: v1
Metadata:
name: traefik-ingress-service
namespace: kube-system
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- protocol: TCP
port: 80
name: web
- protocol: TCP
port: 8080
name: admin
type: NodePort
node1节点:
[root@k8s-node1 ~]# wget http://192.168.15.253/k8s-tools/docker_k8s_traefik.tar.gz
[root@k8s-node1 ~]# docker load -i docker_k8s_traefik.tar.gz
直接创建上面的资源对象即可:(master节点)
[root@k8s-master ingress]# kubectl create -f traefik.yaml
[root@k8s-master ingress]# kubectl get pod -n kube-system
再回到node1节点上查看端口:
[root@k8s-node1 ~]# netstat -ntupl
浏览器访问10.0.0.12:8080
创建ingress规则:
Master节点:
[root@k8s-master ingress]# cd …/tomcat_demo/
[root@k8s-master tomcat_demo]# cp …/ingress/ingress.yaml .
[root@k8s-master tomcat_demo]# vim ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
Metadata:
name: tomcat
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: tomcat.oldqiang.com
http:
paths:- backend:
serviceName: myweb
servicePort: 8080
[root@k8s-master tomcat_demo]# kubectl create -f ingress.yaml
[root@k8s-master tomcat_demo]# kubectl get ingresses
- backend:
[root@k8s-master tomcat_demo]# kubectl scale rc myweb --replicas=2
[root@k8s-master tomcat_demo]# kubectl get pod
做好本地解析;浏览器访问tomcat.oldqiang.com,
traefik 还提供了一个 web ui 工具,就是上面的 8080 端口对应的服务,为了能够访问到该服务,我们这里将服务设置成的 NodePort:
现在在浏览器中输入 10.0.0.12:8080就可以访问到 traefik 的 dashboard 了:
现在还没有实现负载均衡,
[root@k8s-master tomcat_demo]# cd …/ingress/
[root@k8s-master tomcat_demo]# kubectl delete -f ingress.yaml
[root@k8s-master tomcat_demo]# kubectl create -f ingress.yaml
[root@k8s-master tomcat_demo]# kubectl get ingresses
[root@k8s-master tomcat_demo]# kubectl get pod
[root@k8s-master tomcat_demo]# kubectl exec -it myweb-nlqfg /bin/bash
root@myweb-nlqfg:/usr/local/tomcat# cd webapps/
root@myweb-nlqfg:/usr/local/tomcat/webapps# ls
ROOT demo docs examples host-manager manager
root@myweb-nlqfg:/usr/local/tomcat/webapps# cd demo/
root@myweb-nlqfg:/usr/local/tomcat/webapps/demo# ll
bash: ll: command not found
root@myweb-nlqfg:/usr/local/tomcat/webapps/demo# ls
1.html WEB-INF index.jsp input.html insert.jsp
root@myweb-nlqfg:/usr/local/tomcat/webapps/demo# echo ‘oldboy’ >1.html
然后浏览器访问:http://tomcat.oldqiang.com/demo/1.html
再刷新一遍:
实现了负载均衡;
创建Ingress 对象
创建一个 ingress 对象
apiVersion: extensions/v1beta1
kind: Ingress
Metadata:
name: traefik-Nginx
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: Nginx.oldqiang.com
http:
paths:
查看traefik dashboard,此时多了一条记录
第三步:优化
#增加一行hostPort: 80
ports:
- name: http
containerPort: 80
hostPort: 80
添加以后hostPort: 80,然后更新应用:
$ kubectl apply -f traefik.yaml
这个时候我们在浏览器中直接使用http://Nginx.oldqiang.com访问
- K8s的附加组件
k8s集群中dns服务的作用,就是将svc的名称解析成对应VIP地址
7.1 dns服务
安装dns服务
1:下载dns_docker镜像包(node2节点10.0.0.13)
wget http://192.168.15.253/docker_images/docker_k8s_dns.tar.gz
2:导入docker_k8s_dns.tar.gz镜像包(node2节点10.0.0.13)
3:创建dns服务
vi skydns-rc.yaml
…
spec:
nodeName: 10.0.0.13
containers:
kubectl create -f skydns.yaml
kubectl create -f skydns-svc.yaml
4:检查
kubectl get all --namespace=kube-system
5:修改所有node节点kubelet的配置文件
vim /etc/kubernetes/kubelet
KUBELET_ARGS="–cluster_dns=10.254.230.254 --cluster_domain=cluster.local"
systemctl restart kubelet
6:修改tomcat-rc.yml
env:
- name: MysqL_SERVICE_HOST
value: ‘MysqL’ #修改前值是VIP
kubectl delete -f .
kubectl create -f .
7:验证
[K8s指定容器的初始命令:
args
command:
Dockerfile指定
ENTRYPOINT]
7.2 namespace命令空间
namespace做资源隔离(对资源进行分组),一个业务一个namespace
7.3 健康检查和可用性检查
7.3.1 探针的种类
livenessProbe:健康状态检查(存活探针),周期性检查服务是否存活,检查结果失败,将重新启动一个容器
readinessProbe:可用性检查(就绪探针),周期性检查服务是否可用,不可用将从service的endpoints中移除
7.3.2 探针的检测方法
• exec:执行一段命令 返回值为0, 非0 [Redis info MysqL]
• httpGet:检测某个 http 请求的返回状态码 2xx,3xx正常, 4xx,5xx错误 [web服务]
• tcpsocket:测试某个端口是否能够连接
使用场景:
exec: 没有web界面 Redis MysqL
httpget: web界面
7.3.3 liveness探针的exec使用
vi Nginx_pod_exec.yaml
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:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 5
successthreshold: 1
failureThreshold: 1
7.3.4 liveness探针的httpGet使用
vi Nginx_pod_httpGet.yaml
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
7.3.5 liveness探针的tcpsocket使用
vi Nginx_pod_tcpsocket.yaml
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
7.3.6 readiness探针的httpGet使用
vi 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
7.4 dashboard服务
1:上传并导入镜像,打标签
2:创建dashborad的deployment和service
3:访问http://10.0.0.11:8080/ui/
全局资源
局部资源(namespace)
Daemon sets 适合做监控 node-exporter 3个 deployment走调度,配置文件里不需要指定副本数,
Pet sets 宠物应用、有状态应用(pod名字是固定的 01 02 03)
Statsfulset: 数据库的应用,redis elasticsearch MysqL
其他:畜生应用、无状态应用(pod后的名字是随机的)
Jobs:任务,[一次性任务 complate]
pod:一直运行
Cronjobs:定时任务
Service:四层负载均衡
Ingress:七层负载均衡
Pvc和pv:密码
secret:密码,密钥
config maps:配置文件
daemonset:不需要指定副本数,不需要scheduler调度,应用场景:刚好一个node节点只需要跑一个服务的应用
deployment:需要指定副本数,需要scheduler调度,随机调动,
7.5 通过apiservicer反向代理访问service
第一种:NodePort类型
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30008
第二种:ClusterIP类型
type: ClusterIP
ports:
- port: 80
targetPort: 80
http://10.0.0.11:8080/api/v1/proxy/namespaces/命令空间/services/service的名字/
#例子:
http://10.0.0.11:8080/api/v1/proxy/namespaces/qiangge/services/wordpress
8. k8s弹性伸缩
弹性伸缩前提条件:需要附加插件heapster监控(heapster,influxdb,grafana)
弹性伸缩规则的名字:HPA (kubectl autoscale)
8.1 使用heapster实现弹性伸缩
Heapster架构:
主服务heapster通过连接api-server获取node节点信息,
1:上传并导入镜像,打标签
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:上传配置文件,kubectl create -f .
修改配置文件:
#heapster-controller.yaml
spec:
nodeName: 10.0.0.13
containers:
- name: heapster
image: 10.0.0.11:5000/heapster:canary
imagePullPolicy: IfNotPresent
#influxdb-grafana-controller.yaml
spec:
nodeName: 10.0.0.13
containers:
3:打开dashboard验证
- name: myweb
image: 10.0.0.11:5000/Nginx:1.13
ports:
缩容:
- 使用kubeadm初始化k8s集群
由于二进制安装的k8s: 步骤繁琐,于是就有大佬用ansibe和saltstack来简化二进制安装流程
ansible 一键自动化安装 https://github.com/easzlab/kubeasz
saltstack 一键自动化安装 https://github.com/unixhot/salt-k8s
kubeadm安装k8s: 需要google官方的docker镜像,需要解决网络问题
9.1 环境要求:
机器名 ip地址 cpu和内存要求
kubernetes-master 10.0.0.15 2c2g(关闭swap)
kubernetes-node1 10.0.0.16 2c2g(关闭swap)
9.2 安装指定版本docker
#所有节点
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
sed -i ‘s+download.docker.com+mirrors.tuna.tsinghua.edu.cn/docker-ce+’ /etc/yum.repos.d/docker-ce.repo
yum list docker-ce --showduplicates
#安装指定版本的docker
yum install docker-ce-18.09.7 -y
9.3 安装kubeadm
#所有节点
cat < /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum install kubelet-1.15.5-0 kubeadm-1.15.5-0 kubectl-1.15.5-0 -y
systemctl enable kubelet && systemctl start kubelet
9.4 使用kubeadm初始化k8s集群
#所有节点
cat < /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
swapoff -a
vim /etc/fstab
#控制节点
kubeadm init --kubernetes-version=v1.15.0 --image-repository registry.aliyuncs.com/google_containers --pod-network-cidr=10.244.0.0/16 --service-cidr=10.254.0.0/16
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown
(
i
d
−
u
)
:
(id -u):
(id−u):(id -g) $HOME/.kube/config
9.5 给k8s集群加入node节点:
#node节点
kubeadm join 10.0.0.11:6443 --token 47hq6d.uvtn5ymfah6egl53
–discovery-token-ca-cert-hash sha256:ff283c3350b5dfa0ac8c093383416c535485ec18d5cdd6b82273e0d198157605
9.6 为k8s集群配置网络插件
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
#修改网段范围为
kubectl create -f kube-flannel.yml
kubectl get all -n kube-system
kubectl get nodes
9.7 为k8s集群配置dashboard服务
kubeadm安装k8s 1.15部署dashboard
wget https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
vi kubernetes-dashboard.yaml
#修改service类型为NodePort类型
kubectl create -f kubernetes-dashboard.yaml
#解决Google浏览器不能打开kubernetes dashboard方法
mkdir key && cd key
#生成证书
openssl genrsa -out dashboard.key 2048
openssl req -new -out dashboard.csr -key dashboard.key -subj ‘/CN=10.0.0.11’
openssl x509 -req -in dashboard.csr -signkey dashboard.key -out dashboard.crt
#删除原有的证书secret
kubectl delete secret kubernetes-dashboard-certs -n kube-system
#创建新的证书secret
kubectl create secret generic kubernetes-dashboard-certs --from-file=dashboard.key --from-file=dashboard.crt -n kube-system
#查看pod
kubectl get pod -n kube-system
#删除pod,启动新pod生效
kubectl delete pod -n kube-sytem kubernetes-dashboard-7c697b776b-zph98
#编辑文件vim k8s-admin.yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
Metadata:
name: admin
annotations:
rbac.authorization.kubernetes.io/autoupdate: “true”
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: admin
namespace: kube-system
apiVersion: v1
kind: ServiceAccount
Metadata:
name: admin
namespace: kube-system
labels:
kubernetes.io/cluster-service: “true”
addonmanager.kubernetes.io/mode: Reconcile
kubectl create -f k8s-admin.yaml
kubectl get serviceaccount -n kube-system
kubectl describe serviceaccount admin -n kube-system
kubectl describe secret admin-token-29977 -n kube-system
#保存查看到的token密钥,就是登录dashboard需要的令牌
9.8 使用metric-server实现弹性伸缩
安装metric-server
必须要有dns
Master节点:
#上传k8s_yaml.tar.gz
rz
tar xf k8s_yaml.tar.gz
cd k8s_yaml/
node节点:导入docker_k8s_addon_resizer.tar.gz和docker_k8s_metrics_server.tar.gz镜像
rz
docker load -i docker_k8s_addon_resizer.tar.gz
docker load -i docker_k8s_metrics_server.tar.gz
master节点:
cd k8s_yaml/metrics/
#创建
[root@kubernetes-master metrics]#kubectl create -f .
#查看pod状态;
[root@kubernetes-master metrics]#kubectl get pod -n kube-system
[root@kubernetes-master metrics]# kubectl top node
实现弹性伸缩
[root@kubernetes-master metrics]# cd
[root@kubernetes-master ~]# vim k8s_deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
Metadata:
name: Nginx
spec:
replicas: 3
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
minReadySeconds: 30
template:
Metadata:
labels:
app: Nginx
spec:
containers:
- name: Nginx
image: Nginx:1.13
ports:
- containerPort: 80
resources:
limits:
cpu: 100m
requests:
cpu: 100m
在node1节点上导入Nginx镜像docker_Nginx1.13.tar.gz
[root@kubernetes-node1 ~]# rz
[root@kubernetes-node1 ~]# docker load -i docker_Nginx1.13.tar.gz
Master节点:
[root@kubernetes-master ~]# kubectl create -f k8s_deploy.yaml
[root@kubernetes-master ~]# kubectl get pod -o wide
创建弹性伸缩规则:
[root@kubernetes-master ~]# kubectl autoscale deployment Nginx --max=10 --min=1 --cpu-percent=10
#查看资源
[root@kubernetes-master ~]# kubectl get all
[root@kubernetes-master ~]# cp k8s_yaml/ingress/ingress.yaml Nginx_ingress.yaml
[root@kubernetes-master ~]# vim Nginx_ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
Metadata:
name: Nginx
annotations:
kubernetes.io/ingress.class: traefik
spec:
rules:
- host: Nginx.oldqiang.com
http:
paths:
[root@kubernetes-master ~]# kubectl create -f Nginx_ingress.yaml
[root@kubernetes-master ~]# kubectl get ingresses
做好本地hosts解析,浏览器访问Nginx.oldqiang.com
命令行访问;
[root@kubernetes-master ~]# vim /etc/hosts
[root@kubernetes-master ~]# curl -I http://Nginx.oldqiang.com/
弹性伸缩:
浏览器访问10.0.0.15:30005页面,选择容器组发现有三个节点,过了一会就剩一个了
[root@kubernetes-master ~]# kubectl get hpa
压力测试:
[root@kubernetes-master ~]# yum -y install httpd-tools&>/dev/null
[root@kubernetes-master ~]# ab -n 5000000 -c 200 http://Nginx.oldqiang.com/
再次访问浏览器我们就会看到效果:
最后查看一下每个pod和node占多少资源:
[root@kubernetes-master ~]# kubectl top pod
[root@kubernetes-master ~]# kubectl top node
五分钟以后会自动把pod撤掉
10. 持久化存储
为什么要做持久化存储?
为了保证数据不丢失
数据持久化类型:
10.1 emptyDir:
emptyDir:临时的空目录,[随着pod的生命周期,删除、创建,保存容器里面需要独自保存的数据]
Deployment pod 3个
emptyDir的使用场景:
存放日志
spec:
nodeName: 10.0.0.13
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
10.2 HostPath:[不能跨宿主机做数据共享]
查看帮助:kubctl explain pod.spec
spec:
nodeName: 10.0.0.12
volumes:
- name: MysqL
hostPath:
path: /data/wp_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
10.3 Nfs(网络文件共享)
volumes:
- name: MysqL
nfs:
path: /data/wp_MysqL
server: 10.0.0.11
10.4 pv和pvc:
pv: persistent volume 全局资源(在所有namespace里都能看到),k8s集群
一个PV对接一个存储,(不同的存储设置不同的目录)
存储能力(后端能提供的大小)
pvc: persistent volume claim, 局部资源(属于某一个具体的namespace)
PV提供存储能力-PVC选择适合存储
回收:pvc删除、PV清空
删除:PVC删除、PV也删除
PVC:需要存储能力–只有有适合PV的时候才会绑定,一旦绑定则无法分配给别的PV
10.4.1 创建pv和pvc
上传yaml配置文件,创建pv和pvc
10.4.2 创建MysqL-rc,pod模板里使用volume
volumes:
- name: MysqL
persistentVolumeClaim:
claimName: tomcat-MysqL
10.4.3 验证持久化
验证方法1:删除MysqL的pod,数据库不丢
kubectl delete pod MysqL-gt054
验证方法2:查看nfs服务端,是否有MysqL的数据文件
存储:
- 块存储 块设备(格式化挂载后使用) 硬盘 cinder lvm
- 文件存储 无需格式化挂载就可使用, nfs glusterfs eg:nfs
- 对象存储 有专门的数据库,利用哈希校验值校验后端是否存在,eg:百度网盘、QQ
fatsdfs Swift
存储还分为硬件存储(ras san) 和软件存储(nfs lvm 分布式存储;最终数据还是落在硬盘上,只提供存储功能,)
10.5 分布式存储ceph
[分布式存储和单机存储;
分布式存储介绍:增加副本数添加安全性 ,
Ceph: 支持块存储、文件存储;
Ceph架构:
RADOS:(可靠的、自主的分布式存储)
原理:大文件分割N个4M的文件、然后进行分组、每个组有自己的pgid、然后按组存入OSD中、存几份取决于有几个副本、默认三个副本
object :即把一个大文件切割成N个4M的小文件;
pgs :将那些小文件进行分组;
OSD:按组进行存储,默认分成三个副本;
[ceph集群之间使用万兆网络]
一个 间隔一段时间 添加一个
Osd:–data –日志盘使用固态硬盘作为日志盘
osd: --data -journal
ceph-deploy osd create --filestore --fs-type xfs --data /dev/sdc --journal
data/log storage1
部署ceph:使用ceph-deploy部署(实现块存储)[写时复制:用多少分多少])
10.0.0.14 ceph01
10.0.0.15 ceph02
10.0.0.16 ceph03
#配置免密码登录
Ceph01安装
#ceph01初始化ceph配置文件(创建集群) ceph-deploy new --public-network 10.0.0.0/24 ceph01 ceph02 ceph03
#ceph01安装rpm包
yum install ceph ceph-mon ceph-mgr ceph- radosgw.x86_64 ceph-mds.x86_64 ceph-osd.x86_64 -y
#ceph初始化集群:
ceph-deploy mon create-initial
#ceph管理员用户配置admin用户
ceph-deploy admin ceph01 ceph02 ceph03
#安装并启动ceph-manager
ceph-deploy mgr create ceph01 ceph02 ceph03
#创建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
#创建pool资源池
ceph osd pool create k8s 128 128
#在资源池里创建块设备rbd
rbd create --size 1024 k8s/tomcat_MysqL.img
#如何使用rdb(映射块设备到本地)
rbd feature disable k8s/tomcat_MysqL.img object-map fast-diff deep-flatten
rbd map k8s/tomcat_MysqL.img
mkfs.xfs /dev/rbd0 #映射成功后格式化硬盘
mount /dev/rbd0 /mnt #挂载
#扩容
rbd resize --size 2048 k8s/tomcat_MysqL.img
umount /mnt
xfs_growfs /dev/rbd0
rbd info k8s/tomcat_MysqL.img
ceph对接k8s
pod资源对接ceph( https://github.com/kubernetes/examples/tree/master/volumes/rbd)
·rbd类型:
#k8s中node节点上都安装rbd(ceph-common)
上传cpeh文件压缩包并解压
[root@k8s-node01 ~]# wget http://192.168.15.253/ceph_common.tar.gz
[root@k8s-node01 ~]# tar xf ceph_common.tar.gz
安装
[root@k8s-node01 ~]# cd ceph_common/
[root@k8s-node01 ceph_common]# yum -y localinstall *.rpm
#给k8s中所有的node节点发送ceph节点的keyring文件和ceph.conf文件
[root@ceph01 ~]# cd /etc/ceph/
[root@ceph01 ceph]# scp ceph.client.admin.keyring root@10.0.0.12:pwd
[root@ceph01 ceph]# scp ceph.client.admin.keyring root@10.0.0.13:pwd
[root@ceph01 ceph]# scp ceph.conf root@10.0.0.12:pwd
[root@ceph01 ceph]# scp ceph.conf root@10.0.0.12:pwd
#取admin用户的秘钥
grep key /etc/ceph/ceph.client.kube.keyring |awk ‘{printf “%s”, $NF}’|base64
[root@k8s-master ceph]# cat ceph-secret.yaml
apiVersion: v1
kind: Secret
Metadata:
name: ceph-secret
namespace: tomcat
type: " kubernetes.io/rbd"
data:
key: QVFCczV0RmZIVG8xSEJBQUxUbm5TSWZaRFl1VDZ2aERGeEZnWXc9PQ==
[root@k8s-master ceph]# kubectl create -f ceph-secret.yaml
#创建rbd
rbd create --size 2048 --image-feature layering k8s/test2.img
[root@k8s-master ceph]# cat test_ceph_pod.yml
apiVersion: v1
kind: Pod
Metadata:
name: rbd3
namespace: tomcat
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: test2.img
fsType: ext4
user: admin
secretRef:
name: ceph-secret
查看状态:
[root@k8s-master ceph]# kubectl describe -n tomcat pod rbd
验证:
[root@k8s-master ceph]# kubectl get pod -n tomcat
NAME READY STATUS RESTARTS AGE
MysqL-snr00 0/1 Error 0 22h
myweb-g5667 1/1 Running 1 1d
rbd 1/1 Running 0 16m
[root@k8s-master ceph]# kubectl exec -n tomcat -it rbd /bin/bash
root@rbd:/# df -h
·cephfs对接ceph(文件存储;)
实现文件存储:安装 ceph-matedata-server
实现对象存储:安装ceph-radosgw ]
- 使用jenkins实现k8s持续更新
ip地址 服务 内存
10.0.0.11 kube-apiserver 8080 1G
10.0.0.12 kube-apiserver 8080 1G
10.0.0.13 jenkins(tomcat + jdk) 8080 2G
代码仓库使用gitee托管
构建完镜像推送到私有仓库
11.1 安装gitlab并上传代码
#a:安装
wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-11.9.11-ce.0.el7.x86_64.rpm
yum localinstall gitlab-ce-11.9.11-ce.0.el7.x86_64.rpm -y
#b:配置
vim /etc/gitlab/gitlab.rb
external_url ‘http://10.0.0.13’
prometheus_monitoring[‘enable’] = false
#c:应用并启动服务
gitlab-ctl reconfigure
#使用浏览器访问http://10.0.0.13,修改root用户密码,创建project
#上传代码到git仓库
cd /srv/
rz -E
unzip xiaoniaofeifei.zip
rm -fr xiaoniaofeifei.zip
git config --global user.name “Administrator”
git config --global user.email “admin@example.com”
git init
git remote add origin http://10.0.0.13/root/xiaoniao.git
git add .
git commit -m “Initial commit”
git push -u origin master
11.2 安装jenkins,并自动构建docker镜像
1:安装jenkins
cd /opt/
wget http://192.168.12.201/191216/apache-tomcat-8.0.27.tar.gz
wget http://192.168.12.201/191216/jdk-8u102-linux-x64.rpm
wget http://192.168.12.201/191216/jenkin-data.tar.gz
wget http://192.168.12.201/191216/jenkins.war
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
2:访问jenkins
访问http://10.0.0.12:8080/,默认账号密码admin:123456
3:配置jenkins拉取gitlab代码凭据
a:在jenkins上生成秘钥对
ssh-keygen -t rsa
b:复制公钥粘贴gitlab上
c:jenkins上创建全局凭据
4:拉取代码测试
5:编写dockerfile并测试
#vim dockerfile
FROM 10.0.0.11:5000/Nginx:1.13
add . /usr/share/Nginx/html
添加docker build构建时不add的文件
vim .dockerignore dockerfile
docker build -t xiaoniao:v1 . docker run -d -p 88:80 xiaoniao:v1
打开浏览器测试访问xiaoniaofeifei的项目
6:上传dockerfile和.dockerignore到私有仓库
git add docker .dockerignore
git commit -m “fisrt commit”
git push -u origin master
7:点击jenkins立即构建,自动构建docker镜像并上传到私有仓库
修改jenkins 工程配置
docker build -t 10.0.0.11:5000/test:v
B
U
I
L
D
I
D
.
d
o
c
k
e
r
p
u
s
h
10.0.0.11
:
5000
/
t
e
s
t
:
v
BUILD_ID . docker push 10.0.0.11:5000/test:v
BUILDID.dockerpush10.0.0.11:5000/test:vBUILD_ID
7.3 jenkins自动部署应用到k8s
kubectl -s 10.0.0.11:8080 get nodes
if [ -f /tmp/xiaoniao.lock ];then
docker build -t 10.0.0.11:5000/xiaoniao:v
B
U
I
L
D
I
D
.
d
o
c
k
e
r
p
u
s
h
10.0.0.11
:
5000
/
x
i
a
o
n
i
a
o
:
v
BUILD_ID . docker push 10.0.0.11:5000/xiaoniao:v
BUILDID.dockerpush10.0.0.11:5000/xiaoniao:vBUILD_ID
kubectl -s 10.0.0.11:8080 set image -n xiaoniao deploy xiaoniao xiaoniao=10.0.0.11:5000/xiaoniao:vKaTeX parse error: Undefined control sequence: \d at position 85: …p -oP '(?<=80:)\̲d̲+'` echo "你…port"
echo “更新成功”
else
docker build -t 10.0.0.11:5000/xiaoniao:v
B
U
I
L
D
I
D
.
d
o
c
k
e
r
p
u
s
h
10.0.0.11
:
5000
/
x
i
a
o
n
i
a
o
:
v
BUILD_ID . docker push 10.0.0.11:5000/xiaoniao:v
BUILDID.dockerpush10.0.0.11:5000/xiaoniao:vBUILD_ID
kubectl -s 10.0.0.11:8080 create namespace xiaoniao
kubectl -s 10.0.0.11:8080 run xiaoniao -n xiaoniao --image=10.0.0.11:5000/xiaoniao:vKaTeX parse error: Undefined control sequence: \d at position 205: …p -oP '(?<=80:)\̲d̲+'` echo "你…port"
echo “发布成功”
touch /tmp/xiaoniao.lock
chattr +i /tmp/xiaoniao.lock
fi
jenkins一键回滚
kubectl -s 10.0.0.11:8080 rollout undo -n xiaoniao deployment xiaoniao
12. k8s高可用
12.1 安装配置etcd高可用集群
#所有节点安装etcd
yum install etcd -y
3:ETCD_data_dir="/var/lib/etcd/"
5:ETCD_LISTEN_PEER_URLS=“http://0.0.0.0:2380”
6:ETCD_LISTEN_CLIENT_URLS=“http://0.0.0.0:2379”
9:ETCD_NAME=“node1” #节点的名字
20:ETCD_INITIAL_ADVERTISE_PEER_URLS=“http://10.0.0.11:2380” #节点的同步数据的地址
21:ETCD_ADVERTISE_CLIENT_URLS=“http://10.0.0.11:2379” #节点对外提供服务的地址
26:ETCD_INITIAL_CLUSTER=“node1=http://10.0.0.11:2380,node2=http://10.0.0.12:2380,node3=http://10.0.0.13:2380”
27:ETCD_INITIAL_CLUSTER_TOKEN=“etcd-cluster”
28:ETCD_INITIAL_CLUSTER_STATE=“new”
systemctl enable etcd
systemctl restart etcd
[root@k8s-master tomcat_demo]# etcdctl cluster-health
member 9e80988e833ccb43 is healthy: got healthy result from http://10.0.0.11:2379
member a10d8f7920cc71c7 is healthy: got healthy result from http://10.0.0.13:2379
member abdc532bc0516b2d is healthy: got healthy result from http://10.0.0.12:2379
cluster is healthy
#修改flannel
vim /etc/sysconfig/flanneld
FLANNEL_ETCD_ENDPOINTS=“http://10.0.0.11:2379,http://10.0.0.12:2379,http://10.0.0.13:2379”
etcdctl mk /atomic.io/network/config ‘{ “Network”: “172.18.0.0/16”,“Backend”: {“Type”: “vxlan”} }’
systemctl restart flanneld
systemctl restart docker
12.2 安装配置master01的api-server,controller-manager,scheduler(127.0.0.1:8080)
vim /etc/kubernetes/apiserver
KUBE_ETCD_SERVERS="–etcd-servers=http://10.0.0.11:2379,http://10.0.0.12:2379,http://10.0.0.13:2379"
vim /etc/kubernetes/config
KUBE_MASTER="–master=http://127.0.0.1:8080"
systemctl restart kube-apiserver.service
systemctl restart kube-controller-manager.service kube-scheduler.service
12.3 安装配置master02的api-server,controller-manager,scheduler(127.0.0.1:8080)
yum install kubernetes-master.x86_64 -y
scp -rp 10.0.0.11:/etc/kubernetes/apiserver /etc/kubernetes/apiserver
scp -rp 10.0.0.11:/etc/kubernetes/config /etc/kubernetes/config
systemctl stop kubelet.service
systemctl disable kubelet.service
systemctl stop kube-proxy.service
systemctl disable kube-proxy.service
systemctl enable kube-apiserver.service
systemctl restart kube-apiserver.service
systemctl enable kube-controller-manager.service
systemctl restart kube-controller-manager.service
systemctl enable kube-scheduler.service
systemctl restart kube-scheduler.service
12.4 为master01和master02安装配置Keepalived
yum install keepalived.x86_64 -y
#master01配置:
! 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
}
}
#master02配置
! 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
}
}
systemctl enable keepalived
systemctl start keepalived
12.5 所有node节点kubelet,kube-proxy指向api-server的vip
vim /etc/kubernetes/kubelet
KUBELET_API_SERVER="–api-servers=http://10.0.0.10:8080"
vim /etc/kubernetes/config
KUBE_MASTER="–master=http://10.0.0.10:8080"
systemctl restart kubelet.service kube-proxy.service
- 基于nfs实现动态存储(二进制)
当你创建PVC时系统自动创pv
实现动态存储的方式:
Nfs的动态存储方式:
部署nfs
Master节点 node1node2节点安装nfs
yum -y install nfs
master节点:
mdkir /data
[root@k8s-master k8s_yaml]# mkdir storageclass
[root@k8s-master k8s_yaml]# cd storageclass
[root@k8s-master storageclass]#vi nfs-client.yaml
ikind: Deployment
apiVersion: apps/v1
Metadata:
name: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
Metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
- name: NFS_SERVER
value: 10.0.0.13
- name: NFS_PATH
value: /data
volumes:
- name: nfs-client-root
nfs:
server: 10.0.0.13
path: /data
vi nfs-client-sa.yaml
iapiVersion: v1
kind: ServiceAccount
Metadata:
name: nfs-client-provisioner
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
Metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: [“persistentvolumes”]
verbs: [“get”, “list”, “watch”, “create”, “delete”] - apiGroups: [""]
resources: [“persistentvolumeclaims”]
verbs: [“get”, “list”, “watch”, “update”] - apiGroups: [“storage.k8s.io”]
resources: [“storageclasses”]
verbs: [“get”, “list”, “watch”] - apiGroups: [""]
resources: [“events”]
verbs: [“list”, “watch”, “create”, “update”, “patch”] - apiGroups: [""]
resources: [“endpoints”]
verbs: [“create”, “delete”, “get”, “list”, “watch”, “patch”, “update”]
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
Metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
vi nfs-client-class.yaml
iapiVersion: storage.k8s.io/v1
kind: StorageClass
Metadata:
name: course-nfs-storage
provisioner: fuseim.pri/ifs
修改pvc的配置文件
Metadata:
namespace: tomcat
name: pvc-01
annotations:
volume.beta.kubernetes.io/storage-class: “course-nfs-storage”
14. Helm k8s包管理工具
14.1 helm介绍: [部署应用变得更简单、高效]
secret
configmap
deployment
pvc
service
ingress
14.2 helm安装
master节点:
上传helm文件
[root@kubernetes-master ~]#wget http://192.168.15.253/helm
[root@kubernetes-master ~]# chmod +x helm
[root@kubernetes-master ~]# mv helm /usr/sbin/
[root@kubernetes-master ~]# helm version
这里只有客户端,helm服务端需要配置在k8s的集群中
14.3 helm初始化
helm init #可以指定很多参数
helm init --upgrade -i slpcat/tiller:v2.8.2 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
[可以部署helm的服务端]
Node节点:
[root@kubernetes-node1 ~]# http://192.168.15.253/k8s-tools/docker_k8s_tiller.tar.gz
[root@kubernetes-node1 ~]# docker load -i docker_k8s_tiller.tar.gz
Master节点:helm init 会自动生成yaml文件,应用于k8s中
[root@kubernetes-master ~]# helm init
[root@kubernetes-master ~]# kubectl get pod -n kube-system |grep tiller
[root@kubernetes-master ~]# helm version
到这里我们的helm服务端就部署OK了
#安装好helm之后,默认tiller没有权限
Master节点:
[root@kubernetes-master ~]# cd helm
vi rbac.yaml
iapiVersion: v1
kind: ServiceAccount
Metadata:
name: tiller
namespace: kube-system
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
Metadata:
name: tiller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: tiller
namespace: kube-system
创建用户
kubectl create -f rbac.yaml
更新配置文件
第一种方式:手动修改配置文件
kubectl edit -n kube-system deployments tiller-deploy
找到serviceAcount,把用户名手动改成tiller
第二种方式:命令行非交互式打补丁
kubectl patch -n kube-system deploy tiller-deploy -p ‘{ “spec”:{ “template”:{ “spec”:{ “serviceAccount”: “tiller” } } } }’
创建完成后查看一下:
kubectl get deployments -n kube-system tiller-deploy -o yaml |grep -i account
#helm命令行自动补全
helm completion bash > .helmrc && echo “source .helmrc” >> .bashrc
source .helmrc
[root@kubernetes-master helm]# helm install --name oldboy --namespace=oldboy stable/PHPmyadmin
helm search MysqL
helm install –name wordpress stable/MysqL
helm inspect values stable/MysqL
14.4 自定义helm
[root@kubernetes-master helm]# mkdir helm_chart
[root@kubernetes-master helm]# cd helm_chart
[root@kubernetes-master helm_chart]# helm create hello-helm
官方会自动生成hello-helm目录,这个目录里面会有所有的模板文件
[root@kubernetes-master helm_chart]# ls
hello-helm
[root@kubernetes-master helm_chart]# cd hello-helm/
[root@kubernetes-master hello-helm]# ls
charts Chart.yaml templates values.yaml
[root@kubernetes-master charts]# cd templates/
[root@kubernetes-master templates]# rm -rf *.yaml *.tpl tests
[root@kubernetes-master templates]# ls
NOTES.txt
[root@kubernetes-master templates]# vim NOTES.txt
hello!
[root@kubernetes-master helm_chart]# cd hello-helm/
[root@kubernetes-master hello-helm]# ls
charts Chart.yaml templates values.yaml
[root@kubernetes-master hello-helm]# vim values.yaml
[root@kubernetes-master helm_chart]# helm install --name test hello-helm/
Error: release test Failed: namespaces “default” is forbidden: User “system:serviceaccount:kube-system:tiller” cannot get resource “namespaces” in API group “” in the namespace “default”
遇到这个报错,是因为tiller服务器的权限不足
执行以下命令添加权限:
[root@kubernetes-master helm_chart]# kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
[root@kubernetes-master helm_chart]# kubectl patch deploy --namespace kube-system tiller-deploy -p ‘{“spec”:{“template”:{“spec”:{“serviceAccount”:“tiller”}}}}’
然后在安装就OK了
[root@kubernetes-master helm_chart]# helm install --name test hello-helm/
[root@kubernetes-master helm_chart]# helm list
这样就安装成功了
[root@kubernetes-master helm_chart]# cd hello-helm/
[root@kubernetes-master hello-helm]# cd templates/
[root@kubernetes-master templates]# vim pod.yaml
[root@kubernetes-master templates]# cd …
[root@kubernetes-master hello-helm]# ls
charts Chart.yaml templates values.yaml
[root@kubernetes-master hello-helm]# vim values.yaml
[root@kubernetes-master hello-helm]# cd templates/
[root@kubernetes-master templates]# vim pod.yaml
在这里不能以容器的名字作为变量:
再次安装,这次我们不指定名字,会随机生成一个名字
[root@kubernetes-master hello-helm]# helm install …/hello-helm
查看一下,发现这次安装的helm的名字是随机生成的:
[root@kubernetes-master hello-helm]# helm list
我们在values里面写的valum值通过helm部署的时候,会解析成最终的值,[这个过程称为渲染,所谓渲染就是把templates里面的值替换成values的值]然后创建yaml文件,就完成了部署
如果需要只渲染不部署,需要参数:–debug --dry-run
[root@kubernetes-master hello-helm]# helm install …/hello-helm --debug --dry-run
改变模板里面的值:参数:–set
[root@kubernetes-master hello-helm]# helm install …/hello-helm --debug --dry-run --set podname.test=oldguo
升级:
[root@kubernetes-master hello-helm]# helm upgrade test …/hello-helm --set podname.test=oldguo
[root@kubernetes-master hello-helm]# helm list
卸载:delete
[root@kubernetes-master hello-helm]# helm delete modest-dragonfly
[root@kubernetes-master hello-helm]# kubectl get all -n modest-dragonfly
查看没有资源了,卸载成功
- statsfulset资源(公司不常用)
有状态的应用 有数据的应用 MysqL es集群(数据库)
特点:
所有的pod都是有序的(创建一个PVC会自动创建一个PV)
eg: web statsfulset
web-0
web-1
#启动pod,使用默认的动态存储
所有节点安装nfs-utils
yum -y install nfs-utils
master节点:
[root@kubernetes-master ~]# mkdir /data
[root@kubernetes-master ~]# vim /etc/exports
/data 10.0.0.0/24(rw,sync,no_root_squash,no_all_squash)
[root@kubernetes-master ~]# systemctl restart rpcbind
[root@kubernetes-master ~]# systemctl restart nfs
[root@kubernetes-master ~]# systemctl enable nfs
Node节点:
[root@kubernetes-node1 ~]# showmount -e 10.0.0.15
Export list for 10.0.0.15:
/data 10.0.0.0/24
Master节点:
[root@kubernetes-master ~]# cd k8s_yaml/
[root@kubernetes-master k8s_yaml]# ls
dashboard dns heapster helm ingress k8s_test.yaml metrics tomcat_demo volumes
上传storageclass.tar.gz文件
[root@kubernetes-master k8s_yaml]# rz
[root@kubernetes-master k8s_yaml]# tar xf storageclass.tar.gz
[root@kubernetes-master k8s_yaml]# cd storageclass/
[root@kubernetes-master storageclass]# ls
nfs-client.yaml nfs-sc.yaml rbac.yaml test_pvc2.yaml test_pvc.yaml
[root@kubernetes-master storageclass]# rm -rf test_pvc.yaml test_pvc2.yaml
[root@kubernetes-master storageclass]# vim nfs-client.yaml
[root@kubernetes-master storageclass]# vim nfs-sc.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
Metadata:
name: course-nfs-storage
annotations:
storageclass.kubernetes.io/is-default-class: true
provisioner: fuseim.pri/ifs
[root@kubernetes-master storageclass]# kubectl create -f .
这里报错是因为顺序问题,storageclass.kubernetes.io/is-default-class存储默认不存在
[root@kubernetes-master storageclass]# kubectl get pod
查看pod容器状态,如果nfs容器创建很慢,我们就在node节点上配置docker镜像加速文件
[root@kubernetes-node1 ~]# vim /etc/docker/daemon.json
{“registry-mirrors”:[“https://reg-mirror.qiniu.com/”]}
[root@kubernetes-node1 ~]# systemctl restart docker
等nfs容器running之后我们删除重新创建一下,还是报错,最后删除
[root@kubernetes-master storageclass]# vim nfs-sc.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
Metadata:
name: course-nfs-storage
provisioner: fuseim.pri/ifs
然后创建:
[root@kubernetes-master storageclass]# kubectl create -f nfs-sc.yaml
创建成功以后我们创建一个PVC试试
上传PVC文件:
[root@kubernetes-master storageclass]# cd …
[root@kubernetes-master k8s_yaml]# cd tomcat_demo/
[root@kubernetes-master tomcat_demo]# rz -E
[root@kubernetes-master tomcat_demo]# vim MysqL_pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
Metadata:
name: tomcat-MysqL
annotations:
volume.beta.kubernetes.io/storage-class: “course-nfs-storage”
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
[root@kubernetes-master tomcat_demo]# kubectl create -f MysqL_pvc.yaml
创建一个PVC之后会自动创建一个PV
[root@kubernetes-master tomcat_demo]# kubectl get pvc
[root@kubernetes-master tomcat_demo]# kubectl get pv
这里我们可以打标签
[root@kubernetes-master tomcat_demo]# kubectl patch storageclass course-nfs-storage -p ‘{“Metadata”:{“annotations”:{“storageclass.kubernetes.io/is-default-class”:“true”}}}’
[root@kubernetes-master tomcat_demo]# vim MysqL_pvc2.yaml
kind: PersistentVolumeClaim
apiVersion: v1
Metadata:
name: tomcat-MysqL2
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
[root@kubernetes-master tomcat_demo]# kubectl create -f MysqL_pvc2.yaml
[root@kubernetes-master tomcat_demo]# kubectl get pvc
将提前准备好的sts配置文件上传
[root@kubernetes-master k8s_yaml]# mkdir sts
[root@kubernetes-master k8s_yaml]# cd sts
[root@kubernetes-master sts]# rz
[root@kubernetes-master sts]# ls
sts.tar.gz
[root@kubernetes-master sts]# tar xf sts.tar.gz
[root@kubernetes-master sts]# ls
sts sts.tar.gz
[root@kubernetes-master sts]# mv sts/* .
[root@kubernetes-master sts]# ls
k8s_svc.yaml Nginx_sts.yml sts sts.tar.gz
[root@kubernetes-master sts]# rm -rf sts sts.tar.gz
[root@kubernetes-master sts]# ls
k8s_svc.yaml Nginx_sts.yml
[root@kubernetes-master sts]# kubectl create -f .
[root@kubernetes-master sts]# kubectl get sts
[root@kubernetes-master sts]# kubectl get pod
同时会自动创建两个PVC:
[root@kubernetes-master sts]# kubectl get pvc
如果没有动态存储,不会自动创建PVC,所以要想做statsfulset,必须要有动态存储
直接使用域名访问
ping web-1.Nginx.default.svc.cluster.local
ping MysqL.default.svc.cluster.local
kubectl patch storageclass course-nfs-storage -p '{“Metadata”: {“annotations”:{" storageclass.kubernetes.io/is-default-class":“true”}}}
[root@kubernetes-master sts]# yum -y install bind-utils
[root@kubernetes-master sts]# kubectl get pod -n kube-system -o wide
[root@kubernetes-master sts]# ping 10.244.0.8
可以ping通
[root@kubernetes-master sts]# dig @10.244.0.8 web-1.Nginx.default.svc.cluster.local
可以解析IP
[root@kubernetes-master sts]# kubectl get pod -o wide
servicename: Nginx (无头 service 不分配clusterIP)
16. job资源和cron.job资源
job的作用:
运行一次性容器
使用k8s的job清理es索引
master节点:
[root@kubernetes-master ~]# cd k8s_yaml/
[root@kubernetes-master k8s_yaml]# mkdir job
[root@kubernetes-master k8s_yaml]# cd job
[root@kubernetes-master job]# vi k8s_job.yaml
iapiVersion: batch/v1
kind: Job
Metadata:
name: Nginx
spec:
template:
Metadata:
name: myjob
spec:
containers:
- name: Nginx
image: Nginx:1.13
ports:
- containerPort: 80
command: [“sleep”,“10”]
restartPolicy: Never
[root@kubernetes-master job]# kubectl create -f k8s_job.yaml
[root@kubernetes-master job]# kubectl get job
任务完成以后,pod自动关闭
[root@kubernetes-master job]# kubectl get pod
[root@kubernetes-master job]# vi k8s_cronjob.yaml
iapiVersion: batch/v1beta1
kind: CronJob
Metadata:
name: Nginx
spec:
schedule: ‘*/1 * * * *’
jobTemplate:
spec:
template:
Metadata:
name: myjob
spec:
containers:
- name: Nginx
image: Nginx:1.13
ports:
- containerPort: 80
command: [“sleep”,“10”]
restartPolicy: Never
[root@kubernetes-master job]# kubectl create -f k8s_cronjob.yaml
[root@kubernetes-master job]# kubectl get cronjob.batch
- kubesphere管理平台
17.1 kubesphere是什么?
kubesphere—以应用为中心的容器管理平台,完全开源,KubeSphere 帮助企业在云、虚拟化及物理机等任何环境中快速构建、部署和运维基于 Kubernetes 的容器架构,轻松实现微服务治理、多租户管理、DevOps 与 CI/CD、监控日志告警、应用商店、大数据、以及人工智能等业务场景。
Kubernetes平台,专为DevOps团队量身定制
极简、易用、灵活、高效
17.2 部署kubesphere
部署方式:
• 部署k8s集群及kubesphere
• 已有kubernetes集群部署kubesphere
已有k8s集群部署kubesphere具有更高的灵活性
架构:
KubeSphere 采用了前后端分离的架构设计,后端的各个功能组件可通过 REST API 对接外部系统,详见 架构说明。本仓库仅包含后端代码,前端代码参考 Console 项目。
核心功能:
功能 介绍
多云与多集群管理 提供多云与多集群的中央管理面板,支持集群导入,支持应用在多云与多集群一键分发
Kubernetes 集群搭建与运维 支持在线 & 离线安装、升级与扩容 K8s 集群,支持安装 “云原生全家桶”
Kubernetes 资源可视化管理 可视化纳管原生 Kubernetes 资源,支持向导式创建与管理 K8s 资源
基于 Jenkins 的 DevOps 系统 支持图形化与脚本两种方式构建 CI/CD 流水线,内置 Source to Image(S2I)和 Binary to Image(B2I)等 CD 工具
应用商店与应用生命周期管理 提供应用商店,内置 Redis、MysqL 等 15 个常用应用,支持应用的生命周期管理
基于 Istio 的微服务治理 (Service Mesh) 提供可视化无代码侵入的 灰度发布、熔断、流量治理与流量拓扑、分布式 Tracing
多租户管理 提供基于角色的细粒度多租户统一认证,支持 对接企业 LDAP/AD,提供多层级的权限管理
丰富的可观察性功能 提供集群/工作负载/Pod/容器等多维度的监控,提供基于多租户的日志查询与日志收集,支持节点与应用层级的告警与通知
基础设施管理 支持 Kubernetes 节点管理,支持节点扩容与集群升级,提供基于节点的多项监控指标与告警规则
存储管理 支持对接 Ceph、glusterFS、NFS、Local PV,支持可视化运维管理 PVC、StorageClass,提供 CSI 插件对接云平台存储
网络管理 提供租户网络隔离与 K8s Network Policy 管理,支持 Calico、Flannel,提供 Porter LB 用于暴露物理环境 K8s 集群的 LoadBalancer 服务
GPU support 集群支持添加 GPU 与 vGPU,可运行 TensorFlow 等 ML 框架
部署k8s集群:
hostnamectl set-hostname xx
yum install -y chrony
systemctl enable --Now chronyd
timedatectl set-timezone Asia/Shanghai
在云平台上启动三台虚拟机
https://kubesphere.com.cn/en/docs/installing-on-linux/introduction/multioverview/
18. 阿里云k8s
pvc --pv —阿里云存储
svc --loadbalance
阿里云环境安装K8S步骤
- 安装docker
yum install -y docker - 修改 /etc/docker/daemon.json 文件并添加上 registry-mirrors 键值
vim /etc/docker/daemon.json
{
“registry-mirrors”: [“https://registry.docker-cn.com”]
}
3. 启动并测试
sudo systemctl start docker
sudo docker run hello-world
4. 安装 etcd
sudo yum install etcd -y
5. kubectl安装
wget https://dl.k8s.io/v1.10.0/kubernetes-client-linux-amd64.tar.gz
tar -xzvf kubernetes-client-linux-amd64.tar.gz
cd kubernetes/client/bin
sudo chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
6. 安装VirtualBox 安装
vim /etc/yum.repos.d/virtualBox.repo
#具体内容如下:
[virtualBox]
name=Oracle Linux / RHEL / CentOS-$releasever /
b
a
s
e
a
r
c
h
−
V
i
r
t
u
a
l
B
o
x
b
a
s
e
u
r
l
=
h
t
t
p
:
/
/
d
o
w
n
l
o
a
d
.
v
i
r
t
u
a
l
b
o
x
.
o
r
g
/
v
i
r
t
u
a
l
b
o
x
/
r
p
m
/
e
l
/
basearch - VirtualBox baseurl=http://download.virtualBox.org/virtualBox/rpm/el/
basearch−VirtualBoxbaseurl=http://download.virtualBox.org/virtualBox/rpm/el/releasever/$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://www.virtualBox.org/download/oracle_vBox.asc
#执行以下命令,完成VirtualBox 的安装
yum -y install VirtualBox-5.2
- 安装minikube
curl -Lo minikube http://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/releases/v0.30.0/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/ - 安装依赖,配置virtualBox
yum -y install kernel-devel kernel-devel-3.10.0-957.el7.x86_64
sudo /sbin/vBoxconfig - 主板的bios中的Intel Virtualization Technology设置成了disable的,重启电脑进入bios,将其设置成abled
- 注意VMware的虚拟机开启VT-X/AMD-v enabled
解决方式:
step 1:关闭虚拟机(注意:是关闭,不是挂起;否则为关机状态下,下图不能勾选!)
step 2 :